8
votes

I have two applications, one as a peripheral (on iPad 4th Gen running iOS 7) and one as central (iPhone 5c running iOS7).

I wish to have a writable characteristic within the peripheral device that the central writes a handful of bytes to (approx 4 bytes but could vary from execution to execution).

I am configuring the peripheral as follows:

-(void)startPeripheral
{
    CBMutableService *service = [[CBMutableService alloc]initWithType:[CBUUID UUIDWithString:kMyServiceUUID] primary:YES];
    CBMutableCharacteristic *ch = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:kMyWriteUUID] properties:CBCharacteristicPropertyWrite value:nil permissions:CBAttributePermissionsWriteable];
    service.characteristics = @[ch];

    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@[[CBUUID UUIDWithString:kMyServiceUUID]], CBAdvertisementDataServiceUUIDsKey, @"My Peripheral", CBAdvertisementDataLocalNameKey, nil];

    [self.peripheralManager addService:service];
    [self.peripheralManager startAdvertising:dict];

    NSLog(@"Service = %@",service);
}

This all appears to work at first, the peripheral advertises the service and my central can scan, find, discovers service and characteristics and find the characteristic it's interested in. The problem comes when I try to write to the characteristic.

On the central I have the following method:

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    NSLog(@"Service/Characteristics = %@",service.characteristics);
    for(CBCharacteristic *ch in service.characteristics)
    {
        NSLog(@"Characteristic properties = %x",ch.properties);
        NSLog(@"Characterisctic = %@",ch.UUID);
        if([ch.UUID isEqual:[CBUUID UUIDWithString:kMyWriteUUID]])
        {
            // We've found our write characteristic
            NSLog(@"Writing data to characteristic %@",ch.UUID);
            NSData *data = [NSData dataWithBytes:(Byte[]){1,2,3,4} length:4];
            [peripheral writeValue:data forCharacteristic:ch type:CBCharacteristicWriteWithResponse];
        }
    }
 }

I get a callback to didWriteValueForCharacteristic which indicates the error:

Error Domain=CBATTErrorDomain Code=14 "Unlikely error."

Which is not very helpful.

Can anyone spot and issues or suggest any solutions?

Thanks, Rich

3
Googling this problem it appears I'm not the only person who has experienced it. I've also found the Bluetooth LE stack to be highly unstable requiring regular device reboots to fix issues. Also if I run the peripheral on the iPhone 5c I cannot connect to it, I can only connect to the peripheral when it is run on the iPad. I'm fast coming to the conclusion that the peripheral support in the Core Bluetooth libraries doesn't work properly. - Richard Baxter
Did you ever find more information and/or a resolution? I'm also seeing the dreaded "unlikely error". (It doesn't seem that unlikely. 8) ) - AndrewCr

3 Answers

0
votes

It's not obvious to me what is the error but:

  1. You ought to start advertising only after receiving the peripheralManager:didAddService:error: callback.
  2. Could you attach the corresponding device console logs? (use the Organizer->Phone->Console)
0
votes

Try not adding your service until you get the following callback:

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral

You then check the peripheral's state for CBPeripheralManagerStatePoweredOn. It's invalid to add services while the peripheral is not powered on.

0
votes

I got the same error when I miss-typed the delegate on the peripheral side, double check the implemented delegate signatures

f.e. I've written

-(void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequest:(NSArray *)requests

instead of

-(void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests

(see the missing 's' in the first version)