My question is how can we detect our own device's unique bluetooth ID (must be available from other device when we scan for nearby available bluetooth)
I tried this
CBUUID *myService = [CBUUID UUIDWithString: #"MyServiceID"];
but in my case this is same as device UUDI.
You can’t. Apple works hard to ensure that apps can not access any identifiers that uniquely identify a device; the Bluetooth MAC address would be such an identifier.
The Bluetooth identifiers that are reported by Core Bluetooth on another iOS device are local to that device.
You could allocate your own UUID and make that available via a characteristic. That way you would know what value the remote device would see, but it would need to connect to retrieve the value. You could also put a specific name in the advertising data.
Related
See the image above. I am pairing my iOS app from iphone1 to a single Bluetooth device, say BT1, which is further inter-connected with other similar bluetooth devices via Bluetooth Mesh. As soon as I connect with BT1, I get a uuid1 for the connection.
Now, I need to uniquely identify the paired device uuid. This is essential as I would like to transfer my phone app settings to another iPhone, say iPhone2, via cloud, so that any phone can connect to the original paired BT device. But when I try to pair iPhone2 to Device1, I get a different uuid2 for Device1, because of which, I cannot match it with the uuid1. So if uuid1 = uuid2, then the cloud will send me the original settings.
Question -
1. is it technically possible to ensure that a bluetooth device shares the same uuid to all its client?
2. If #1 is no, is there an alternative?
Thanks in adv.
So I have peripheral BLE device and I need some identifier for it to later share with another iPhone. Example I connect with iPhone 'A' to peripheral. iPhone 'A' saves peripheral's identifier to database and later I easily can take iPhone 'B' and connect to the peripheral found by this identifier.
Now there is UUID what changes for every iPhone-peripheral connection, but MAC
Address is not available. What could you suggest?
If you do not manufacture the peripheral yourself then you can not uniquely identify peripherals across different iOS devices. This is exactly how Apple wants it to be since it means that developers can't track user's locations or movement patterns based on device addresses. It would be a privacy concern.
If you manufacture the peripheral yourself then you can do pretty much whatever you want. For example: Use a custom Service uuid, add uuid to manufacturer data in advertisement, set unique advertisement names, etc etc.. But if the core purpose of all this is to track your user then I would guess that Apple might deny your submission.
I have a similar problem and many thread like this say you cannot obtain MAC address by CoreBluetooth. I want to connect to a BLE peripheral (I mean open and connectable peripheral) and store some information on a database so that a different iPhone can read the same database and use the informations when it connects to the same kind of BLE peripheral. For now I rely on the device name, obtained like this:
-(void)addDiscoveredDevice:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSString * name = [peripheral name];
}
because NSString * uuid = [[peripheral identifier] UUIDString]; gives me different results on different iOS devices.
Therefore, let's say my first problem is to know how many Apple Watch I have close to my iPhone, the second problem is to know if a given Apple Watch (e.g. John's Apple Watch) is close to my iPhone. Unfortunately this method doesn't work because users (e.g. John) or companies can change the name of their peripherals.
Yes I can rely on a combination of name + service uuid + characteristic uuid but for the same reasons, if the name changes it is useless.
Does anybody found a solution?
I faced a problem about CoreBluetooth Framework.
As Example, I have two devices and each device performs both advertising and scanning. So, I use CBCentralManager and CBPeripheralManager on each.
So, to simplify problem, let's assume that Device1 is broadcasting and Device2 scanning.
When CBCentralManager on Device2 discover the Device1, callback
centralManager:didDiscoverPeripheral:advertisementData:RSSI:
is called and I can get Device1 identifier by calling [peripheral.identifier UUIDString].
How then I can get my local device (Device2) Identifier?
I mean in case that both devices are advertising, Device1 will discover Device2 too and get it's peripheral identifier, but
How can I get exact this identifier (some kind of self-address) on Device2?
P.S. I know that this Identifier is not unique for each device and can change over the time, it's not a problem.
Unfortunately you can't do this. The identifier returned by [peripheral.identifier UUIDString] is auto generated by iOS on the receiving device. It is seeded by the transmitter Mac address (which does not change) and the time the device starts being seen by iOS (which does change).
Because of the second factor is not predictable and the fact that the id generation algorithm is not published, you cannot predict what this id will be on the transmitter side.
Bottom line, if you want a predictable unique id, you cannot use this field
I came across this new API from iOS 7.
- (NSArray *)retrieveConnectedPeripheralsWithServices:(NSArray *)serviceUUIDs NS_AVAILABLE(NA, 7_0);
So its pretty clear that if the return array count is greater than 0 than its connected to atleast one device.
But before using this API I am not able to figure it out the argument (serviceUUIDs) that I have to passed here.
Can someone explain here with an example?
You can't use this method unless you know at least one service exposed by the device. You could try using a common service, such as Device Information - 0x180A - as most BLE devices will advertise this service but it is not guaranteed.
CBUUID *deviceInfoUUID = [CBUUID UUIDWithString: #"180A"];
[cbCentral retrieveConnectedPeripheralsWithServices:#[deviceInfoUUID]];
Legacy audio devices (headsets, A2DP devices etc) are visible as audio devices through the audio session classes -
Detect attached audio devices iOS
The services and characteristics of a peripheral are identified by 128-bit Bluetooth-specific UUIDs, which are represented in the Core Bluetooth framework by CBUUID objects. Though not all UUIDs that identify a service or characteristic are predefined by the Bluetooth Special Interest Group (SIG), Bluetooth SIG has defined and published a number of commonly used UUIDs that have been shortened to 16-bits for convenience. For example, Bluetooth SIG has predefined the 16-bit UUID that identifies a heart rate service as 180D. This UUID is shortened from its equivalent 128-bit UUID, 0000180D-0000-1000-8000-00805F9B34FB, which is based on the Bluetooth base UUID that is defined in the Bluetooth 4.0 specification, Volume 3, Part F, Section 3.2.1.
The CBUUID class provides factory methods that make it much easier to deal with long UUIDs when developing your app. For example, instead of passing around the string representation of the heart rate service’s 128-bit UUID in your code, you can simply use the UUIDWithString method to create a CBUUID object from the service’s predefined 16-bit UUID, like this:
CBUUID *heartRateServiceUUID = [CBUUID UUIDWithString: #"180D"];
When you create a CBUUID object from a predefined 16-bit UUID, Core Bluetooth prefills the rest of 128-bit UUID with the Bluetooth base UUID.
For more, please read documentation
Different Bluetooth device offer different services associated with it, and these services offered by a particular device can be identified through a specific UUID associated with it.
For more details on bluetooth services and their respective UUID, please refer following link :
https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
So when you perform a search you can specify a criteria which suggest the preference of your bluetooth devices to search.
so if you want the bluetooth devices offering the blood pressure and heart rate in your search preference you should them as following :
[bluetoothmanager scanForPeripheralsWithServices:[NSArray arrayWithObjects:[CBUUID UUIDWithString:#"1810"], [CBUUID UUIDWithString:#"180D"], nil] options:nil];
UPDATE :
Refer following heading on the below link:
Discovering Peripheral Devices That Are Advertising
https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/PerformingCommonCentralRoleTasks/PerformingCommonCentralRoleTasks.html#//apple_ref/doc/uid/TP40013257-CH3-SW1
it is mentioned in NOTE that if you pass nil it will return all devices:
Note: If you specify nil for the first parameter, the central manager returns all discovered peripherals, regardless of their supported services. In a real app, you will likely specify an array of CBUUID objects, each of which represents the universally unique identifier (UUID) of a service that a peripheral is advertising. When you specify an array of service UUIDs, the central manager returns only peripherals that advertise those services, allowing you to scan only for devices that you may be interested in.
UUIDs, and the CBUUID objects that represent them, are discussed in more detail in “Services and Characteristics Are Identified by UUIDs.”
So you can use it as following :
[bluetoothmanager scanForPeripheralsWithServices:nil options:nil];
And it will serve your purpose :)
For BLE 4.0, it provides API to discover peripherals with array of service UUID.
I just want to find the specific one. How to achieve this ?
If need assign the identifier to the specific device, how to do it ?
(I think my question need some context of core bluetooth of iOS. )
The process for reconnecting to known peripherals is described in the Core Bluetooth Programming Guide.
Essentially if you know the UUID of the device you want to reconnect to (which is the identifier property of the CBPeripheral object) then you can use the retrievePeripheralsWithIdentifiers: method of the CBCentralManager to obtain the CBPeripheral object and then attempt a connection -
NSUUID *pid=[[NSUUID alloc]initWithUUIDString:#"45D956BB-75E4-6CEB-C06C-D531B00174E4" ];
NSArray *peripherals=[self.centralManager retrievePeripheralsWithIdentifiers:#[pid]];
if ([peripherals count]>0)
{
CBPeripheral *peripheral=[peripherals objectAtIndex:0];
peripheral.delegate=self;
[self.connectingPeripherals addObject:peripheral];
NSLog(#"Found peripheral %# with name %#",peripheral.identifier,peripheral.name);
[self.centralManager connectPeripheral:peripheral options:nil];
}
This may not work, and you may have to scan for your peripheral as the identifier of some peripherals (iOS devices in particular) periodically change their UUID.
The programming guide notes -
Note: A peripheral device may not be available to be connected to for
a few reasons. For instance, the device may not be in the vicinity of
the central. In addition, some Bluetooth low energy devices use a
random device address that changes periodically. Therefore, even if
the device is nearby, the address of the device may have changed since
the last time it was discovered by the system, in which case the
CBPeripheral object you are trying to connect to doesn’t correspond to
the actual peripheral device. If you cannot reconnect to the
peripheral because its address has changed, you must rediscover it
using the scanForPeripheralsWithServices:options: method.
You will also have to scan the first time you encounter a peripheral.
Tell me if I'm wrong. You have 2 devices working as central role who wants to connect to one BLE peripheral.
What it is important is the UUID of the services in the BLE peripheral. From your devices in central role you should search peripherals with a wanted UUID Service. Thats all.
To develop with iOS please follow Core Bluetooth Programming Guide. You have a good tutorial there.
As an example of the Apple documentation:
[myCentralManager scanForPeripheralsWithServices:nil options:nil];
In this line of code you can add an Array of UUID objects (CBUUID) instead of nil for scanForPeripheralsWithServices: