Unable to discover services for retrieved peripheral

Hi,


I'm having problems discovering services for peripherals that have been retrieved using myCentral:retrievePeripheralsWithIdentifiers. I have no problem discovering serivces (and characteristics) for peripherals that have been identified with myCentral:scanForPeripheralsWithServices. I've searched tha varioius forums high and low and see no discussions that indicate that there might be a problem with retrieving peripherals so I assume it is something wrong that I'm doing but I just don't see what. Any pointers would be welcome.


My environment is: iPhone 6 running iOS 8.4, xcode 6.4 and a T.I. CC2541-based peripheral


The scanning sequence works fine as follows:


Initialise CBCentralManager and wait for confirmation that BLE is powered up and ready:


    eventQueue = dispatch_queue_create("com.ekko-tech.mycentral", DISPATCH_QUEUE_SERIAL);
    dispatch_set_target_queue(eventQueue, dispatch_get_main_queue());
    [self setCentralManager:[[CBCentralManager alloc] initWithDelegate:self queue:eventQueue options:bleInitOptions]];


- (void)centralManagerDidUpdateState:(CBCentralManager *)central
.....

else if ([central state] == CBCentralManagerStatePoweredOn) {
.....


Scan for peripherals providing the service I'm looking for:

    NSArray *services = [NSArray arrayWithObject:
                         [CBUUID UUIDWithString:
                          [[[[[self appContext] objectForKey:@"gampResources"] objectForKey:@"Services"]
                            objectForKey:@"Gamp"]
                           objectForKey:@"kGAServiceUUID"]]];
    [centralManager scanForPeripheralsWithServices:services options:bleScanOptions];


As peripheral(s) are discovered, store the one selected by the user (CBPeriferal and NSUID) in local variables. The local variables are held in a global dictionary - ioContext:

        NSArray *dp = [[sc appContext] objectForKey:@"discoveredPeripherals"];
        assert(selectedCellIndex < [dp count]);
    
        [[sc ioContext] setObject:[dp objectAtIndex:selectedCellIndex] forKey:@"thisPeripheral"];
        [[sc ioContext] setObject:[[dp objectAtIndex:selectedCellIndex] identifier] forKey:@"thisPeripheralUUID"];


After the selected peripheral has been sucessfully connected to, store a string representation of the NSUUID in userDefaults:

    NSString *uuidstr = [(NSUUID*)[[[self ioContext] objectForKey:@"thisPeripheral"] identifier] UUIDString];
    assert(uuidstr != nil);
    [[self userDefaults] setValue: uuidstr forKey:@"kLastConnectedPeripheralUUID"];
    [[self userDefaults] synchronize];


Discovering services and characteristics for the above scanned peripheral works just fine. However, the next time the application is run, it will use the NSUUID stored in userDefaults to retrieve that peripheral (before this is eecuted, the initialisation sequence identical to the above is executed - not shown here for brevity):

    NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:[[self userDefaults] objectForKey:@"kLastConnectedPeripheralUUID"]];
    assert(uuid != nil);

    NSArray *knownPeripherals;
    knownPeripherals = [[self centralManager] retrievePeripheralsWithIdentifiers:[NSArray arrayWithObjects:uuid, nil]];
  
    if ([knownPeripherals count] > 0) {
        [[self ioContext] setValue:[knownPeripherals objectAtIndex:0] forKey:@"thisPeripheral"];
        [[self ioContext] setValue:[[knownPeripherals objectAtIndex:0] identifier] forKey:@"thisPeripheralUUID"];
        /
        [[self centralManager] connectPeripheral:[[self ioContext] objectForKey:@"thisPeripheral"] options:bleConnectOptions];
  
    }


The retrieved peripheral connects just fine but subsequent attempts to discover services fail. Specifically, the delegate callback didDiscoverServices is never called:

- (void)doDiscoverService:(NSString *)service {
   
    CBPeripheral *per = [[self ioContext] objectForKey:@"thisPeripheral"];
    CBUUID *suuid = [CBUUID UUIDWithString:[[[[[self appContext] objectForKey:@"gampResources"] objectForKey:@"Services"] objectForKey:service] objectForKey:@"kGAServiceUUID"]];
   
    assert(per != nil);
    assert(suuid != nil);
   
    [[self ioContext] setValue:suuid forKey:@"thisServiceUUID"];
    NSArray *svcArray = [NSArray arrayWithObjects:suuid, nil];
    [per discoverServices:svcArray];
   
}


Since the first service that I want to discover is the battery service, the passed-in string in the above is "Battery"


Regards,


ac

Have you found any solution? I am having the same problem using XCode 7 and Swift, and testing on an iPhone 6s running 9.x and a 6 running 8.3. The discovery of the peripheral succeeds, the connect succeeds, but the call to discoverServices never results in a While I can't find it documented in any Apple materials, I see comments that the didDiscoverServices call back should be called no matter what - either with an error or a collection of services. I have tried passing in an array of services to look for, as well as nil. I have tried waiting several minutes. I have another app that consistently connects to the same peripheral using the same service, so I know the problem is with code.

I also tried running a project from github that uses the same basic connection (https://github.com/MichMich/nRF8001-Swift), and get the same results (after updating the project to work around a lot of complile errors for my updated environment).

Finally, I also tried connecting to a different device with a different service and get the same results. Connection succeeds, but didDiscoverServices never gets called.


These last two points are starting to convince me that this is an iOS bug of some sort.

didDiscoverServices call back should be called no matter what, Personaly i think this is a Core iOS bug issue, if an error or a collection of services isnt aparent..

Unable to discover services for retrieved peripheral
 
 
Q