How to find the specific BLE 4.0 peripheral from two devices with same service UUID - ios

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:

Related

Is it possible to write data on iBeacon

I am going to use iBeacon in my app. Is it possible to write values on it, when the app is opened. If yes how do I achieve this. By using coreBluetooth I can do this.
NSData *bytes = [#"0xDE" dataUsingEncoding:NSUTF8StringEncoding];
[peripheral writeValue:bytes forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
An iBeacon just advertises 3 values; a UUID, a "major" value and a "minor" value.
Beacons typically have some BLE service and characteristics that are used for configuring these and other parameters (such as advertising rate and transmit power) but this is outside of the iBeacon specification; each vendor will have their own service and characteristics.
First you need to know the different between iBeacon(bluetooth beacons) and ordinary Bluetooth device. (You can google it)
The CoreBluetooth function you are calling is for altering values on connected bluetooth peripheral, the keywords are connected bluetooth peripheral which iBeacon is not.
Bluetooth peripherals include GATT server, which allows bluetooth centrals to connect and access its services and characteristics.
While iBeacon just advertises, UUID, major, minor, RSSI. No GATT server, no services or characteristics.
To conclude, there is NO SIMPLE WAY (using bluetooth only) to alter the value ('UUID', 'major', 'minor') on a ORDINARY BEACON.
But some beacon manufacturers do provide some similar solutions, they add extra hardware to beacons (network hard). And provide web portal for beacon owner the control the beacon remotely.
I have developed an app which can modify the iBeacon data of Bluetooth device recently.
There is no standard method in Bluetooth Specification for you to write iBeacon data.
It means that you must use the custom command as you and Bluetooth firmware developer both agree to do this,whatever kind of data communication,different vendor has different methods,both of app developer and Bluetooth firmware developer agree, this is enough!

Unique identifier for peripheral BLE device

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?

Possible to generate a list of connected bluetooth devices for iOS?

I'm trying to determine what devices are connected via bluetooth in iOS but can't seem to figure it out. Ideally I'd like to generate a list of connected bluetooth devices.
I've tried using "retrieveConnectedPeripheralsWithServices" but this requires a specific service to search for. I'd like to generate a list of all connected bluetooth devices, not just specific-service bluetooth devices. Is there a way to just search for all services without looping through all possible services?
Any ideas?
The Solution for iOS:
(Thank you Larme)
NSArray *connectedAccessories = [[EAAccessoryManager sharedAccessoryManager] connectedAccessories];
documentation :
https://developer.apple.com/library/prerelease/ios/documentation/ExternalAccessory/Reference/EAAccessoryManager_class/index.html#//apple_ref/occ/instp/EAAccessoryManager/connectedAccessories
Also if someone needs, this is documentation for Mac :
https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/Bluetooth/BT_Intro/BT_Intro.html
and code snippet for Mac
NSArray *devices = [IOBluetoothDevice pairedDevices];
For alan478's BLE question :
The Core Bluetooth framework provides the classes needed for your iOS and Mac apps to communicate with devices that are equipped with Bluetooth low energy wireless technology. You can take a look this tutorial :
http://www.raywenderlich.com/52080/introduction-core-bluetooth-building-heart-rate-monitor
and BLE code snippet is :
// In this case you need to tell UUID for serching specific device
CBUUID *hrate = [CBUUID UUIDWithString:#"180D"];
// Create a dictionary for passing down to the scan with service method
NSDictionary *scanOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
// Tell the central manager (cm) to scan for the heart rate service
[cm scanForPeripheralsWithServices:[NSArray arrayWithObject:hrate] options:scanOptions]
Please read this document on developer.apple.com :
https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/BestPracticesForInteractingWithARemotePeripheralDevice/BestPracticesForInteractingWithARemotePeripheralDevice.html
here is an interesting paragraph for you :
Explore a Peripheral’s Data Wisely
A peripheral device may have many more services and characteristics than you may be interested in when you are developing an app to fulfill a specific use case. Discovering all of a peripheral’s services and associated characteristics can negatively affect battery life and your app’s performance. Therefore, you should look for and discover only the services and associated characteristics your app needs.
For example, imagine that you are connected to a peripheral device that has many services available, but your app needs access to only two of them. You can look for and discover these two services only, by passing in an array of their service UUIDs (represented by CBUUID objects) to the discoverServices: method of the CBPeripheral class, like this:
[peripheral discoverServices:#[firstServiceUUID, secondServiceUUID]];
After you have discovered the two services you are interested in, you can similarly look for and discover only the characteristics of these services that you are interested in. Again, simply pass in an array of the UUIDs that identify the characteristics you want to discover (for each service) to the discoverCharacteristics:forService: method of the CBPeripheral class.
Also there is this comment :
"think Apple forbids this thing. We can only get list of Devices with specific CBUUID. so if you want to list all the devices(same as the Bluetooth settings does natively) then It is not possible. Please correct me if i am wrong. – Mrug Mar 11 at 13:24"
under this question :
How to get list of available Bluetooth devices?
Swift 5.3
EAAccessoryManager.shared().connectedAccessories
let devices = IOBluetoothDevice.pairedDevices()
// In this case you need to tell UUID for serching specific device
let hrate = CBUUID(string: "180D"),
// Create a dictionary for passing down to the scan with service method
let scanOptions = [CBCentralManagerScanOptionAllowDuplicatesKey : NSNumber(value: false)]
// Tell the central manager (cm) to scan for the heart rate service
cm.scanForPeripherals(withServices: [hrate] as? [CBUUID], options: scanOptions)
peripheral.discoverServices([firstServiceUUID, secondServiceUUID])
There are two cases which you need to consider:
Peripheral may be already connected in the system (iOS connects automatically with some peripherals in order to for example display
battery level). In this case peripheral won't be broadcasting and
detection using scanForPeripherals won't work.
Peripheral is paired, but disconnected. In this case retrieveConnectedPeripherals(withServices:) won't work.
Therefore to retrieve your peripheral you need to combine both things. First you need to check if it's in peripherals returned from retrieveConnectedPeripherals(withServices:). If not you should scanForPeripherals.
If you want to retrieve peripheral which is out of range, you can try to use retrievePeripherals(withIdentifiers:), however it may return also not paired devices and it relies on peripheral's UUID which you have to save after pairing.
Detecting if peripheral is paired
There is one way to detect if the specific peripheral is paired. You need to try to read from protected characteristic (which requires encryption - bonding). If you receive expected data, it means that user accepted pairing request. Otherwise you will receive empty response or none.

XCode: How do you connect to BLE peripheral via UUID?

In my app I am trying to connect to a Bluetooth Low Energy peripheral via. its UUID, but I am not getting any results.
With [_centralManager scanForPeripheralsWithServices:nil options:nil]; I am able to find the peripheral, and in my if (_discoveredPeripheral != peripheral && [peripheral.name isEqual: #"PeripheralName"]) I am able to connect to my device, but only because it's the only device with that name.
When I try to connect via. UUID
myUUID = [CBUUID UUIDWithString:#"My UUID"];
[_centralManager scanForPeripheralsWithServices:[NSArray arrayWithObject:myUUID] options:nil];, I get nothing.
What am I doing wrong?
You put the UUID into the array with services. You do not have a method to scan for a specific device, only devices with specific services.
Your working version is OK, you simply need to iterate through the results and connect to the desired device. Scanning devices for specific services is used for discovery of devices that can support specific services.
So what you are actually doing wrong is you are inserting peripheral UUID into array which expects a service UUID.

iOS CoreBluetooth reconnecting device with UUID

I have a Bluetooth 4.0 (BLE) device using the CC2541 chipset which I am interfacing with via the iOS Core Bluetooth Framework.
I can successfully make a connection to the device using Core Bluetooth when the device is in a discoverable/advertising mode and transfer data to and from the device without any problem.
I maintain a collection of device UUIDs that I have connected with and I am now attempting to connect to one of these devices again using:
CBCentralManager
- (void)retrievePeripherals:(NSArray *)peripheralUUIDs
Calling this function appears to work and I receive a callback to my implementation of the the following function:
CBCentralManagerDelegate
- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
The device I'm attempting to connect with is the one and only peripheral listed in the peripherals array that is passed to this function.
When I then attempt to connect to this device using my connect function (shown below) the connection will not initiate and I get no callbacks at all on either the CBCentralManagerDelegate or the CBPeripheralDelegate.
- (void) connectPeripheral:(CBPeripheral *)peripheral {
NSLog(#"Connecting to peripheral with UUID : %s\r\n",[self UUIDToString:peripheral.UUID]);
activePeripheral = peripheral;
activePeripheral.delegate = self;
[CM connectPeripheral:activePeripheral options:nil];
}
I can make the connection go through successfully, as described above, if I first place the device into discoverable/advertising mode, but this is not a workable solution. The device must allow reconnection without it being placed into discoverable mode.
I did note the answer given to this question CoreBluetooth: What is the lifetime of unique UUIDs suggests I need to pair/bond the BLE device with the iOS device but that this may be dependent on the BLE chipset, the device I'm using is the CC2541. Any advice on how to go about pairing with the device would be most useful, or indeed whether this is a necessary step. I have attempted to watch WWDC 2012: Advanced Core Bluetooth which might give me some assistance, but since Apple were hacked on Thursday I'm not able to access my acccount to watch the video.
Please let me know if any more details are required. The Bluetooth device is stable, but it is being developed internally. If changes may be required to the firmware to assist with the pairing process, I can pass this information along to the electronics team.
Why dont you try this?
It specifies first you need to send a request to a GATT characteristic that requires GATT_AUTHEN_READ permission. Then your CC2541 will respond with INVALID AUTHENTICATION. This will trigger Apple's internal Bonding mechanism and ask for a key. You can enter the passkey and then if the device and CC2541 are successfully paired, it will read the characteristic value and enter your callback.
NOTE: I'm not an iOS developer, but I have worked with CC2541. If you are using the default simplePEripheral example, then a characteristic in simpleProfile characteristic5 requires authentication to read. Take a look at profiles/SimpleProfile/simpleGATTprofile.c

Resources