Bluetooth LE notifications not received on iOS - ios

We are working on a bluetooth project using cordova as a xplatform development tool.
We are developing for android and iOS and writing a BLE plugin for cordova ourselves.
On Android everything is running fine. Now comes the problem:
On iOS we are able to read/write and even subscribe to notifications.
The problem comes when we try to receive a updated value, then nothing happens.
In short
- connect to device
- discover services
- discover characterics
- subscribe to notification characteristic
this is working well:
-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
is getting called, and characteristic.isNotifying is true
When doing a simple read operation on the characteristics, the
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
callback is being called.
Here comes the problem:
When updating the value from the peripheral, the callback simply does not get called.
We have no clue were to look since no errors occur at all, so maybe somebody knows a way to debug this issue?
Note: When connecting to the peripheral using a external tool, subscribing to the characteristic and updating it's value. The notification is received. It's iOS specific.

Ok the problem was:
We were calling [peripheral setNotificaiton:etc] on the temporary peripheral received by the callback.
When we are setting the notification on the onConnected stored peripheral object, notifications are received. (self.peripheral)
No this was not the answer, it was working because we restarted the iOS device. It looks like there is some sort of bug in this crappy apple thing.
Does anybody know how to restart bluetooth programmatically?

Related

delegate of iOS paired device reconnection

I have an application which is using retrieveConnectedPeripheralsWithServices to get the list of paired HID devices. I can get the list and connect to the desired one successfully using connectPeripheral code. When the connection succeeds, following delegate is being called:
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
and for disconnection, I get the corresponded delegate:
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
Now when the HID device gets connected again to the iOS (directly from Setting, not from my application), I want to be informed. Is there any way to find out when an HID device reconnected to the OS?
Finally, I found the answer.
Thanks to #Paulw11 for his guidance, based on Apple Documentation:
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.

Why CBCharacteristic is not updating on each write calls?

Whenever, I am performing a write operation, I have a call of below method: it works! but the problem is that, even if I will be making different calls it will always showing me the output of last result. I am not getting an updated values for the specific commands.
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {...}
To fix this, if we disconnect and then reconnects to the peripheral it will be with updated results.
Couldn't understanding what's wrong happened here?
Is it related to CBCharacteristic object? Can we refresh it? Do we need to refresh a peripheral?
It is only updating if I will restart my BT device. Hence, the answer is short but it took 1 hour for me to get an update on this.

Out of range message and auto-reconnect - BLE Device - IOS

I am currently working on an app that gets data from a BLE device – similar to a heart monitor. The app reads the data from the device and then when it gets a specific amount of data, it creates a .csv file and uploads it into a server. Everything works fine, except when the device gets out of the range. The app just stop receiving data and doesn’t recognize that the connection is lost. I don’t get any error message. The app just stops in the middle of the “getting data” loop and keeps waiting for a data that never comes. When the device is back in the range, nothing happens.
I would like to show an alert informing that the BLE device is out of the range. When the device is in the range again, the app should reconnect to it automatically and then continue reading data from the device. How can I implement that? I tried to get the CM state – using the function below – but it didn’t work.
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
printf("Status of CoreBluetooth central manager changed %d (%s)\r\n",central.state,[self centralManagerStateToString:central.state]);
}
I’ve even tried to add an if clause inside the loop to check the device state, but it didn’t work also.
I am using the Texas instruments chip CC2540.
As suggested by Paulw11 and SJoshi (Thank you guys), I had to implement the didDisconnectPeripheral method. So, here is how I did it:
.h file:
// will be invoked once disconnected
-(void)centralManager:(CBCentralManager *)central
didDisconnectPeripheral:(CBPeripheral *)peripheral
error:(NSError *)error;
.m file:
-(void) centralManager:(CBCentralManager *)central
didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
[central connectPeripheral:peripheral options:nil];
// you can add whatever you want here.
// will execute when the peripheral loose its connection.
}

Reconnect to a BLE device after pulling the battery

I have a BLE device that I am writing an app to pair with. I can discover and connect to the device with no problems. But if I am connected and pull and reinsert the battery on the BLE device I get the didDisconnectPeripheral callback but I never get another didConnectPeripheral even though I'm still scanning. I also tried calling retrieveConnectedPeripheralsWithServices and retrievePeripheralsWithIdentifiers but neither of those return anything.
How can I reliably reconnect after cycling the power on my BLE device?
As soon as the peripheral disconnects you can issue another connect - iOS will automatically reconnect to the device once it is visible again and call your didConnectPeripheral: delegate method
-(void) centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
NSLog(#"Disconnected from peripheral");
[central connectPeripheral:peripheral options:nil];
}
There is no need to rescan/re-discover the peripheral.
You may want a more comprehensive implementation that updates UI etc.
Here is some sample code that connects to a peripheral and displays the vendor information -
https://github.com/paulw11/BTBackground

What the custom UUID mean for BLE in IOS Sample?

I am new to iOS development, and study about Bluetooth Low Energy (BLE, Bluetooth 4.0) for IOS.
I studied the sample code of this link BTLE Central Peripheral Transfer.
And there is another similar sample in this link iOS 7 SDK: Core Bluetooth - Practical Lesson
The applications on the above two links talk about send and receive the text data between two IOS device base on BLE.
The App can select to be a central or Peripheral , and the central will receive the text data send from the Peripheral.
It define the UUID like the following code in header file.
#define TRANSFER_CHARACTERISTIC_UUID #"08590F7E-DB05-467E-8757-72F6FAEB13D4"
And after the Central connect to the Peripheral , it discover the characteristic from Peripheral.
If the UUID is equal to TRANSFER_CHARACTERISTIC_UUID ,then subscribe it by using setNotifyValue:YES like the following code.
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
// Again, we loop through the array, just in case.
for (CBCharacteristic *characteristic in service.characteristics) {
// And check if it's the right one
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
// If it is, subscribe to it
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
// Once this is complete, we just need to wait for the data to come in.
}
The question is like the following:
First Question:
I can not find this UUID:#"08590F7E-DB05-467E-8757-72F6FAEB13D4" in Bluetooth Development Portal.
Is that create by uuidgen in terminal ?
The second Question:
If I am Central ,and I have subscribe the characteristic by using setNotifyValue:YES like the above code.
The BLE will tell the Central there has new data send from Peripheral by following code , is the concept correct ?
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
I am new in IOS development and BLE.
Thanks in advance.
First question:
Yes, Apple even suggests generating those UUIDs using uuidgen in the various WWDC video. The 128-bit UUIDs are not standardized by the Bluetooth SIG and you can use those to run your own profiles.
Second question:
Yes, you first discover the services, then the characteristics, then setNotifyValue:YES. From now on, you will receive notifications from the peripheral via [-CBPeripheralDelegate didUpdateValueForCharacteristic:error:]. The same callback will be invoked when you read a characteristic manually (there's no way to distinguish the read response from a notification in Core Bluetooth).

Resources