50

I'm currently creating an iPhone app (Xcode 4.3.1, IOS 5) that could use Bluetooth devices! Main goal of this application is indoor navigation (GPS inside buildings isn't really accurate).

The only solution I see here (to keep my app on AppStore) is to try scan for available bluetooth devices!

I tried to use CoreBluetooth framework, but I don't get list of available devices! Maybe I don't use these functions correctly

#import <UIKit/UIKit.h>
#import <CoreBluetooth/CoreBluetooth.h>

@interface AboutBhyperView : UIViewController <CBPeripheralDelegate, CBCentralManagerDelegate>
{
    CBCentralManager *mgr;
}
@property (readwrite, nonatomic) CBCentralManager *mgr;
@end



- (void)viewDidLoad
{
    [super viewDidLoad];

    mgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}


- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {


    NSLog([NSString stringWithFormat:@"%@",[advertisementData description]]);
}

-(void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals{
    NSLog(@"This is it!");
}


- (void)centralManagerDidUpdateState:(CBCentralManager *)central{ 
    NSString *messtoshow;

    switch (central.state) {
        case CBCentralManagerStateUnknown:
        {
            messtoshow=[NSString stringWithFormat:@"State unknown, update imminent."];
            break;
        }
        case CBCentralManagerStateResetting:
        {
            messtoshow=[NSString stringWithFormat:@"The connection with the system service was momentarily lost, update imminent."];
            break;
        }
        case CBCentralManagerStateUnsupported:
        {
            messtoshow=[NSString stringWithFormat:@"The platform doesn't support Bluetooth Low Energy"];
            break;
        }
        case CBCentralManagerStateUnauthorized:
        {
            messtoshow=[NSString stringWithFormat:@"The app is not authorized to use Bluetooth Low Energy"];
            break;
        }
        case CBCentralManagerStatePoweredOff:
        {
            messtoshow=[NSString stringWithFormat:@"Bluetooth is currently powered off."];
            break;
        }
        case CBCentralManagerStatePoweredOn:
        {
            messtoshow=[NSString stringWithFormat:@"Bluetooth is currently powered on and available to use."];
            [mgr scanForPeripheralsWithServices:nil options:nil];
            //[mgr retrieveConnectedPeripherals];

//--- it works, I Do get in this area!

            break;
        }   

    }
    NSLog(messtoshow); 
} 

I'm not sure about this line, how to pass correct parameters?

[mgr scanForPeripheralsWithServices:nil options:nil];

I took a look into apple reference .. and I still don't understand what's that CBUUID ??? Every device has some bluetooth id? where can I find it?

- (void)scanForPeripheralsWithServices:(NSArray *)serviceUUIDs options:(NSDictionary *)options;

Parameters serviceUUIDs - An array of CBUUIDs the app is interested in. options - A dictionary to customize the scan, see CBCentralManagerScanOptionAllowDuplicatesKey.

Is there any other way to use Bluetooth on IOS? I mean, older frameworks that don't use BLE 4.0!

any advice would be appreciated!

thanks!

mz87
  • 1,338
  • 2
  • 13
  • 13
  • 1
    Note that when you pass **`nil`** to `scanForPeripheralsWithServices:`, you will not receive any results while backgrounded. – WrightsCS Oct 12 '12 at 21:24
  • @mz87 did you find a way to find BT devices? I'm having the same problem. – Gal Mar 05 '13 at 10:52
  • 3
    I 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 '15 at 13:24
  • @Mrug 6 years later... are you wrong? Does Apple prevent you from getting all connected devices without specifying the UUIDs? I could find a solution for that. – Keselme May 09 '21 at 13:24

5 Answers5

23

This guide looks promising for Bluetooth 3.0. Remember that the CoreBluetooth framework is ONLY for Bluetooth Low Energy (4.0). At bluetooth.com's dev-pages you can see some examples of globally defined services, and as Guan Yang mentionen, you can see that the heart rate service is 0x180D. UUID`s of the unit is defined by the manufacturer.

Here's a code snippet to maybe help you along the way.

// Initialize a private variable with the heart rate service UUID    
CBUUID *heartRate = [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:heartRate] options:scanOptions]
Styx
  • 8,485
  • 8
  • 36
  • 46
chwi
  • 2,663
  • 2
  • 34
  • 62
  • Note, that "Bluetooth low energy, previously known as Wibree is a subset of Bluetooth v4.0" http://en.wikipedia.org/wiki/Bluetooth#Bluetooth_v4.0 So, if a device supports BT 4.0, it does not automatically mean that it does support BT LE. – m8labs Nov 11 '14 at 13:56
  • 1
    @MaratAl I think you got it the opposite way; If the device support LE it doesn't mean it should also support standard BR/EDR. If a device is stamped with the Bluetooth Logo, it should support LE by mu understanding. Branding it "Bluetooth Smart" will probably make it only low energy compatible. – chwi Jan 16 '15 at 09:08
15

in Bluetooth, there are "Services". A device publishes 1..N services, and each service has 1..M characteristics. Each service has an unique identifier, called UUID.

For example, a heart rate Bluetooth Sensor that offers the service "heart rate", publishes a service with UUID 0x180D.

(more services here)

So when you perform a search, you must provide a UUID as the criteria, telling which service to search.

rkyr
  • 2,951
  • 2
  • 19
  • 36
viktorvogh
  • 159
  • 1
  • 2
10

You should take a look at one of the examples. Here’s the relevant line:

[manager scanForPeripheralsWithServices:[NSArray arrayWithObject:[CBUUID UUIDWithString:@"180D"]] options:nil];

(I know this is a Mac OS X example, but the iOS CoreBluetooth API is very similar.)

CBUUID identifies services you are interested in, not devices. Standard services have a 16-bit UUID, in this case 0x180d for the heart rate monitor or perhaps 0x180a for device information, while proprietary services have a 128-bit UUID (16 bytes).

Most devices implement the device information service, so if you are just looking for any device, you could try [CBUUID UUIDWithString:@"180A"].

Guan Yang
  • 1,092
  • 7
  • 6
3

Try giving this while you are scanning for devices

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], CBCentralManagerScanOptionAllowDuplicatesKey, nil];

 [self.centralManager scanForPeripheralsWithServices:nil options:options];

you will be able to get the list of devices at didDiscoverPeripheral delegate method

Michael Dorner
  • 11,986
  • 10
  • 64
  • 95
Jes
  • 88
  • 5
0

Keep calm and use https://github.com/l0gg3r/LGBluetooth

All you need to do

[[LGCentralManager sharedInstance] scanForPeripheralsByInterval:4
                                                         completion:^(NSArray *peripherals) {
     }];

Sunil Chauhan
  • 1,804
  • 14
  • 31
l0gg3r
  • 8,564
  • 3
  • 24
  • 44
  • Don,t get excited same result. If i go to settings/bluetooth i can find some devices, however when i use LGBluetooth i can see none. – iosMentalist Aug 01 '14 at 08:39
  • @Shady, if you connect once to device using LGBluetooth (i.e. pairing) it will be displayed in "Settings" screen, same result with CoreBluetooth. i.e. LGBluetooth simply wraps CoreBluetooth to block based (it doesn't add/remove/change BLE functionality, it only wraps) – l0gg3r Aug 01 '14 at 08:47
  • I don't want to pair or connect, I just want to display all available devices as the "Settings" displays. I wasn't able to do that with CoreBluetooth nor with LGBluetooth. the "centralManger: didDiscoverPeripheral:.." is not being called! – iosMentalist Aug 01 '14 at 09:07
  • @Shady, that functionality should support the peripheral hardware, CoreBluetooth and LGBluetooth will not help you to solve this kind of problems) – l0gg3r Aug 01 '14 at 11:47
  • 2
    Keep calm and dead link :( – Paul Ruiz Nov 09 '15 at 19:24