Mike
Mike

Reputation: 3084

What's the format for the iOS Bluetooth LE kCBAdvDataServiceUUIDs?

In centralManager:didDiscoverPeripheral:advertisementData:RSSI (complete code below), I'm finding a key in the NSDictionary called kCBAdvDataServiceUUIDs. I'm trying to read this data to determine the services available on the device. What format is this data in? The class description is simply

Unknown (<fff0>)

Here's the source:

- (void) centralManager: (CBCentralManager *) central
  didDiscoverPeripheral: (CBPeripheral *) aPeripheral
      advertisementData: (NSDictionary *) advertisementData
                   RSSI: (NSNumber *) RSSI
{
printf("Discovered %s\n", [[aPeripheral name] cStringUsingEncoding: NSUTF8StringEncoding]); // TODO: Remove printfs
    printf("  RSSI: %s\n", [[RSSI stringValue] cStringUsingEncoding: NSUTF8StringEncoding]);
    NSArray *keys = [advertisementData allKeys];
    for (int i = 0; i < [keys count]; ++i) {
        id key = [keys objectAtIndex: i];
        NSString *keyName = (NSString *) key;
        NSObject *value = [advertisementData objectForKey: key];
        if ([value isKindOfClass: [NSArray class]]) {
            printf("   key: %s\n", [keyName cStringUsingEncoding: NSUTF8StringEncoding]);
            NSArray *values = (NSArray *) value;
            for (int j = 0; j < [values count]; ++j) {
                NSObject *aValue = [values objectAtIndex: j];
                printf("       %s\n", [[aValue description] cStringUsingEncoding: NSUTF8StringEncoding]);
                printf("       is NSData: %d\n", [aValue isKindOfClass: [NSData class]]);
            }
        } else {
            const char *valueString = [[value description] cStringUsingEncoding: NSUTF8StringEncoding];
            printf("   key: %s, value: %s\n", [keyName cStringUsingEncoding: NSUTF8StringEncoding], valueString);
        }
    }
}

Here's the output from the keyfob in a TI CC2250 Mini Development Kit:

Discovered (null)
  RSSI: -36
   key: kCBAdvDataServiceUUIDs
       Unknown (<fff0>)
       is NSData: 0
Discovered SimpleBLEPeripheral
  RSSI: -37
   key: kCBAdvDataServiceUUIDs
       Unknown (<fff0>)
       is NSData: 0
   key: kCBAdvDataLocalName, value: SimpleBLEPeripheral
   key: kCBAdvDataTxPowerLevel, value: 0

Upvotes: 3

Views: 9301

Answers (1)

Mike
Mike

Reputation: 3084

After some digging around, here's what I discovered:

The advertisement data passed as a parameter to the centralManager:didDiscoverPeripheral:advertisementData:RSSI is an NSDictionary that always seems to contain at least one key called kCBAdvDataServiceUUIDs. The value associated with this key is an NSArray of objects of type CBUUID.

CBUUID is not documented in the iOS 5 documentation, despite the fact that it is used in many places, including every Apple sample for Bluetooth LE I've seen. Among it's methods is one called data that returns an NSData object. This NSData object has the UUID encoded as a series of bytes.

So, to get and, in this case, view the bytes in the UUIDs of a BLE advertisement, you can use code such as the following:

- (void) centralManager: (CBCentralManager *) central
  didDiscoverPeripheral: (CBPeripheral *) aPeripheral
      advertisementData: (NSDictionary *) advertisementData
                   RSSI: (NSNumber *) RSSI
{
    printf("Discovered %s\n", [[aPeripheral name] cStringUsingEncoding: NSUTF8StringEncoding]); // TODO: Remove printfs
    printf("  RSSI: %s\n", [[RSSI stringValue] cStringUsingEncoding: NSUTF8StringEncoding]);
    NSArray *keys = [advertisementData allKeys];
    for (int i = 0; i < [keys count]; ++i) {
        id key = [keys objectAtIndex: i];
        NSString *keyName = (NSString *) key;
        NSObject *value = [advertisementData objectForKey: key];
        if ([value isKindOfClass: [NSArray class]]) {
            printf("   key: %s\n", [keyName cStringUsingEncoding: NSUTF8StringEncoding]);
            NSArray *values = (NSArray *) value;
            for (int j = 0; j < [values count]; ++j) {
                if ([[values objectAtIndex: j] isKindOfClass: [CBUUID class]]) {
                    CBUUID *uuid = [values objectAtIndex: j];
                    NSData *data = uuid.data;
                    printf("      uuid(%d):", j);
                    for (int j = 0; j < data.length; ++j)
                        printf(" %2X", ((UInt8 *) data.bytes)[j]);
                    printf("\n");
                } else {
                    const char *valueString = [[value description] cStringUsingEncoding: NSUTF8StringEncoding];
                    printf("      value(%d): %s\n", j, valueString);
                }
            }
        } else {
            const char *valueString = [[value description] cStringUsingEncoding: NSUTF8StringEncoding];
            printf("   key: %s, value: %s\n", [keyName cStringUsingEncoding: NSUTF8StringEncoding], valueString);
        }
    }
}

Upvotes: 14

Related Questions