AndroidDev
AndroidDev

Reputation: 21237

BLE Scanning for unknown service

I'm trying to write a toy app to get up to speed on BLE. I have a peripheral device (it's a Tile) that I would like to scan its services. However, I do not know what services it is offering (and I don't see this anywhere in the product's technical specifications). So, I got a list of services from the Bluetooth specs, and am trying to scan for all of them. I'm only assuming that this list is exhaustive, since it doesn't say one way or another.

Here is my code:

- (void)viewDidLoad {
    [super viewDidLoad];    

    // Scan for all available CoreBluetooth LE devices
    _services = @[[CBUUID UUIDWithString:@"1811"],
                  [CBUUID UUIDWithString:@"1815"],
                  [CBUUID UUIDWithString:@"180F"],
                  [CBUUID UUIDWithString:@"1810"],
                  [CBUUID UUIDWithString:@"181B"],
                  [CBUUID UUIDWithString:@"181E"],
                  [CBUUID UUIDWithString:@"181F"],
                  [CBUUID UUIDWithString:@"1805"],
                  [CBUUID UUIDWithString:@"1818"],
                  [CBUUID UUIDWithString:@"1816"],
                  [CBUUID UUIDWithString:@"180A"],
                  [CBUUID UUIDWithString:@"181A"],
                  [CBUUID UUIDWithString:@"1800"],
                  [CBUUID UUIDWithString:@"1801"],
                  [CBUUID UUIDWithString:@"1808"],
                  [CBUUID UUIDWithString:@"1809"],
                  [CBUUID UUIDWithString:@"180D"],
                  [CBUUID UUIDWithString:@"1823"],
                  [CBUUID UUIDWithString:@"1812"],
                  [CBUUID UUIDWithString:@"1802"],
                  [CBUUID UUIDWithString:@"1821"],
                  [CBUUID UUIDWithString:@"1820"],
                  [CBUUID UUIDWithString:@"1803"],
                  [CBUUID UUIDWithString:@"1819"],
                  [CBUUID UUIDWithString:@"1807"],
                  [CBUUID UUIDWithString:@"1825"],
                  [CBUUID UUIDWithString:@"180E"],
                  [CBUUID UUIDWithString:@"1822"],
                  [CBUUID UUIDWithString:@"1806"],
                  [CBUUID UUIDWithString:@"1814"],
                  [CBUUID UUIDWithString:@"1813"],
                  [CBUUID UUIDWithString:@"1824"],
                  [CBUUID UUIDWithString:@"1804"],
                  [CBUUID UUIDWithString:@"181C"],
                  [CBUUID UUIDWithString:@"181D"]];

    CBCentralManager *centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    [centralManager scanForPeripheralsWithServices:_services options:nil];
    self.centralManager = centralManager;
}

- (IBAction)scanForDevices:(UIButton *)sender {
    [_centralManager scanForPeripheralsWithServices:_services options:nil];
}

// CBCentralManagerDelegate - This is called with the CBPeripheral class as its main input parameter.
// This contains most of the information there is to know about a BLE peripheral.
- (void)centralManager:(CBCentralManager *)central
 didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary *)advertisementData
                  RSSI:(NSNumber *)RSSI
{
    NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
    if ([localName length] > 0) {
        NSLog(@"Found the heart rate monitor: %@", localName);
        [self.centralManager stopScan];
        _hRMPeripheral = peripheral;
        peripheral.delegate = self;
        [self.centralManager connectPeripheral:peripheral options:nil];
    }
}

// method called whenever the device state changes.
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    // Determine the state of the peripheral
    if ([central state] == CBCentralManagerStatePoweredOff) {
        NSLog(@"CoreBluetooth BLE hardware is powered off");
    }
    else if ([central state] == CBCentralManagerStatePoweredOn) {
        NSLog(@"CoreBluetooth BLE hardware is powered on and ready");
    }
    else if ([central state] == CBCentralManagerStateUnauthorized) {
        NSLog(@"CoreBluetooth BLE state is unauthorized");
    }
    else if ([central state] == CBCentralManagerStateUnknown) {
        NSLog(@"CoreBluetooth BLE state is unknown");
    }
    else if ([central state] == CBCentralManagerStateUnsupported) {
        NSLog(@"CoreBluetooth BLE hardware is unsupported on this platform");
    }
}

The only log output that I get is this:

CoreBluetooth BLE hardware is powered on and ready

Otherwise, the app runs fine. No errors or warnings. But it never finds the peripheral device.

What am I doing wrong? Is there a different service that I should be scanning for?

Thanks!

EDIT
Using a suggestion below, I scanned the peripheral using the LightBlue app. I now know that there is an advertised service that uses this UUID:

84100CBF-D622-8FF7-C8B8-300FDB52B92D

I changed my array to look like this:

_services = @[[CBUUID UUIDWithString:@"84100CBF-D622-8FF7-C8B8-300FDB52B92D"]];

but still nothing gets output in the log. I also tried passing nil but still nothing.

Upvotes: 0

Views: 1096

Answers (1)

jcaron
jcaron

Reputation: 17710

As pointed out by Paulw, just send nil instead of a service list, and you will get all peripherals in range, whatever the service(s) they advertise.

Note that:

  • this will only work in the foreground. Background scanning requires you to provide services to scan for
  • in your approach, it would not be possible to list all services. Beyond the services with short UUIDs you listed (which are actually shortcuts to full UUIDs), a device can advertise services with any "full" UUID. There are 2^128 possible values...

Upvotes: 1

Related Questions