What the custom UUID mean for BLE in IOS Sample? - ios

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).

Related

Bluetooth LE notifications not received on 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?

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.
}

iOS bluetooth Questions

I want to use my iPad to connect with a OLS426 Bluetooth low energy module to send data thorough the serial port on the Bluetooth module. I have successfully connected to the Bluetooth module. In the connection, the iPad is working as a central and the Bluetooth module as a peripheral.
Here are my questions:
(1)
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
I subscribe to the Bluetooth module in didDiscoverCharacteristicsForService.
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
NSLog(#"Subscribed");
}
After subscribing, the "Subscribed" log is printed on the terminal. Does it mean that I have successfully subscribed to the device?
(2)
I also try to write value for a characteristic in the didDiscoverCharacteristicsForService.
[peripheral writeValue: data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
Since I have set the type to be CBCharacteristicWriteWithResponse, I think that if the writing is not successful, there will be an error. However, there is no error.
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
NSLog(#"Hello sent");
}
My question is why the "Hello sent" is not printed after I set a value for a characteristic?
(3)
I want to send some data thorough the serial port on the bluetooth module. I can only read data from a characteristic, like a heart rate monitor, or write data to a characteristic. In the services of the Bluetooth module, I find one called the "Serial Port" under which there is a characteristic called "FIFO". So I guess that I should write data to that characteristic in order to send data thorough the serial port. Can anyone tell me if my thinking is correct?
1) Yes.
2) didUpdateValueForCharacteristic is called when the characteristic value changes independently of your own write to that characteristic.
3) Have you read the connectBlue document on how to read/write data via the FIFO characteristic?

iOS : How to observe the result of "respondToRequest:withResult" in CoreBluetooth

I have been using CoreBlueTooth framework to communicate between BTLE iOS devices.On the Peripheral side, I received a writing request from Central:
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests{
...
}
According to Apple's doc on CoreBluetooth, I answered with:
[self.peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
However, this method does not have a return value or delegate methods to indicate the result.
Am I missing something?
Please have a look on the documentation provided by Apple about Bluetooth feature
Apple's Bluetooth DOC
respondToRequest:withResult: method is assumed to always successful. You must observe it on Central side at HCI level (probably using hcidump command or btmon if you use linux).

Apple Notification Center Service through OS X

I know you can use this service to have devices like smart watches intercept notifications from iOS devices. But can you receive these iOS notifications on a Mac through OS X?
I want to be able to have my OS X program detect a specific notification type that is received in iOS. I tried browsing for the ANCS device on my Mac, but it didn't show up. I know you can't do this between iOS devices, so I was wondering if maybe the same was true between iOS and OS X or not?
Thanks!
It's definitely possible!
Here's what you need:
An app on your iOS device which imports CoreBluetooth and uses CBPeripheralManager to advertise a dummy service with some custom UUID (not the ANCS UUID, it won't work). This dummy service is required for your Mac to "see" the ANCS service.*
An app on your Mac which imports IOBluetooth, initiates a CBCentralManager object, and starts a scan. You can do this as so:
[self.centralManager scanForPeripheralsWithServices:#[[CBUUID UUIDWithString:YOUR_CUSTOM_SERVICE_UUID]] options:#{CBCentralManagerScanOptionSolicitedServiceUUIDsKey:#[[CBUUID UUIDWithString:ANCS_SERVICE_UUID]]];
Make sure you set yourself up as a delegate to CBCentralManager to receive the delegate callbacks.
When your Mac discovers your device in didDiscoverPeripheral, connect to it:
[self.centralManager connectPeripheral:peripheral options:nil];
1 very important thing to note here is you need to retain your peripheral to a property if you wish to connect to it, otherwise it will be dealloc'ed. See this answer for a more detailed discussion.
In didConnectPeripheral, you need to set yourself up as a delegate to the CBPeripheral you're connected to then start discovering services:
[peripheral discoverServices:nil];
(All the callbacks from this point onward are for CBPeripheral)
In didDiscoverServices, you should get a list of available services. Loop through them as so and discover each service's characteristics:
for (CBService *service in peripheral.services) {
if ([service.UUID isEqual:[CBUUID UUIDWithString:YOUR_CUSTOM_SERVICE_UUID]]) {
NSLog(#"Found your Custom Service");
}
if ([service.UUID isEqual:[CBUUID UUIDWithString:ANCS_UUID]]) {
NSLog(#"Found ANCS Service");
}
[peripheral discoverCharacteristics:nil forService:service];
}
In didDiscoverCharacteristicsForService, you want to look for 3 characteristics:
ANCS Notification Source: UUID 9FBF120D-6301-42D9-8C58-25E699A21DBD (notifiable)
ANCS Control Point: UUID 69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9 (writeable with response)
ANCS Data Source: UUID 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB (notifiable)
For those notifiable characteristics, subscribe to them for updates:
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:ANCS_CHARACTERISTIC_UUID]]) {
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
If you want to check if those characteristics are have started notifying, do a if(characteristic.isNotifying) in didUpdateNotificationStateForCharacteristic.
You will get the actual NSData updates in didUpdateValueForCharacteristic with characteristic.value. The important thing to note here is that you will get informed of notification events by the Notification Source characteristic, but these will not contain that much information. If you want your Mac to play a sound or flash some Hue lights or something like that for every iOS notification, this will suffice. However, for the actual notification details, it will need to come from the Data Source characteristic, but you need to request for them by making very specific calls to the Control Point characteristic. This is where it gets really complicated, and you'll be able to get more information in the official ANCS Specification document.
If you want a shortcut or a look at how others have done it, check out these Github repos:
jamiepinkham/BTLE_ANCS
KhaosT/ANCS-Mac
indragiek/INDANCSClient
Just be careful as you may find bugs in some of these implementations, mainly in the processing of data sent by the ANCS Data Source (I had to get creative with my own error handling).
*** Some may argue that you can use "Service Solicitation" to expose ANCS without having an app running on the iOS device and/or without advertising a dummy Service (see options parameter in Step 2), but I haven't had that much success with it so perhaps there's something I'm missing.

Resources