57

Using CoreBluetooth I want to send data from iPhone to Mac. For this I wrote code like iPhone as 'Peripheral' and Mac as 'Central'.

It works perfectly, but sometimes it disconnects directly and then it continuously connects and disconnects.

Some times when it is trying to reconnect, In Central it directly calls 'didDisconnectPeripheral' delegate method. But some times it has error "The handle is invalid" in 'didUpdateNotificationStateForCharacteristic'.

I referred all the links in net. But I am not able to solve this problem. I thought in iPhone it was storing Bluetooth cache.

Please suggest a solution how to solve "The handle is invalid" error?

Below are some of the important methods.

For Peripheral I wrote Code like below.

In Appdelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.peripheral = [[PeripheralServerObject alloc] init];
self.peripheral.serviceUUID = [CBUUID UUIDWithString:@"4w24"];
return YES;
}

In Peripheral Object File:

//To Check Bluetooth State
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
    switch (peripheral.state) {
        case CBPeripheralManagerStatePoweredOn:
            [self enableService];
            break;
        case CBPeripheralManagerStatePoweredOff: {
            [self disableService];
            break;
        }
}

// To Add characteristics to Service
- (void)enableService
{
[self.peripheral removeAllServices];
 self.service = [[CBMutableService alloc]
                    initWithType:self.serviceUUID primary:YES];

self.authChar =
        [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:@"a86e"]
                                           properties:CBCharacteristicPropertyNotify
                                                value:nil
                                          permissions:CBAttributePermissionsReadable];


self.respChar =
        [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:@"a86f"]
                                           properties:CBCharacteristicPropertyWriteWithoutResponse
                                                value:nil
                                          permissions:CBAttributePermissionsWriteable];

self.service.characteristics = @[ self.authChar, self.respChar ];

    // Add the service to the peripheral manager.
    [self.peripheral addService:self.service];
}

//Peripheral Manager delegate method will be called after adding service.

- (void)peripheralManager:(CBPeripheralManager *)peripheral
            didAddService:(CBService *)service
                    error:(NSError *)error {

    [self startAdvertising];

}

//To disable service 
- (void)disableService
{
 [self.peripheral stopAdvertising];
 [self.peripheral removeAllServices];
}

//To enable a service again.
-(void)refreshService {
    [self disableService];
    [self enableService];
}


If central subscribes the characteristic, then the below peripheral delegate method will be called. In this I implemented code to send data

- (void)peripheralManager:(CBPeripheralManager *)peripheral
                  central:(CBCentral *)central
didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {

    self.dataTimer = [NSTimer scheduledTimerWithTimeInterval:10.0
                                                      target:self
                                                    selector:@selector(sendData)
                                                    userInfo:nil
                                                     repeats:YES];
}

- (void)sendData
{
Here I am sending data like [Apple's BTLE Example Code][1]  
}


//If unsubscribed then I am invalidating timer and refreshing service

- (void)peripheralManager:(CBPeripheralManager *)peripheral
                  central:(CBCentral *)central
didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic {

    if (self.dataTimer)
        [self.dataTimer invalidate];
    [self refreshService];

}

For Mac I wrote a peripheral delegate methods.

//I enables the notification for "a860" Characteristic.

- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverCharacteristicsForService:(CBService *)service
error:(NSError *)error {

     CBUUID * authUUID = [CBUUID UUIDWithString:@"a86e"];
       for (CBCharacteristic *characteristic in service.characteristics) {

        if ([characteristic.UUID isEqual:authUUID]) {
         }
        [self.connectedPeripheral setNotifyValue:YES
                                   forCharacteristic:characteristic];
         }
}

-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
   if (error) {
   Here I am getting error sometimes "The handle is invalid".
    }
}
Matt Taylor
  • 3,270
  • 1
  • 17
  • 34
Suresh
  • 1,005
  • 9
  • 16
  • 1
    I have also seen situations where the peripheral repeatedly connects and disconnects. I suspect that the invalid handle is related to an update that is in progress when the peripheral disconnects. All you can do is attempt to disconnect the peripheral if the state isn't already `CBPeripheralStateDisconnected` and then try to reconnect – Paulw11 Aug 06 '14 at 06:43
  • @Paulw11 thanks for your response.Very few people are responding for CoreBluetooth questions. We tried with disconnecting also, but no use. – Suresh Aug 06 '14 at 09:44
  • I have found that if the peripheral connection becomes unstable you sometimes need to restart the peripheral or bluetooth on the phone to restore stability – Paulw11 Aug 06 '14 at 10:17
  • @Paulw11 Yes.When I disabling the bluetooth 2 to 3 minutes in peripheral or Central solves my problem. But I don't know how to solve programatically? – Suresh Aug 06 '14 at 10:25
  • 1
    Hy does anyone find an answer? I got the same error – Fogia May 12 '15 at 14:33
  • Can we first discover whether peripheral is ready by scanForPeripheralsWithServices: and then trying to connect to the peripheral will solve the problem i guess.Though i don't know why peripheral disconnects and connects automatically unless connect peripheral is happening immediately before discovering services. – Vani Jul 06 '15 at 09:57
  • This problem seems to make the whole of the core-bluetooth library useluss!! – maxisme Aug 08 '15 at 09:01
  • Please post your code for where you actually attempt to connect to the peripheral. – DexterW Aug 13 '15 at 19:21
  • I think this causes your connect and disconnect state, 'didUnsubscribeFromCharacteristic:' since the state is unstable, this will get fired and fired and fired. – NFerocious Aug 19 '15 at 03:13
  • I did not use CoreBluetooth library yet. But As per my past experience while connection iOS deveice to iOS device or iOS deveice to other accessary device, which uses Bonjur framework under the hood, has the same problem. I handled these scenario by killing the connection and readvertising the server. Using Bonjur framework may slove the problem. – deepax11 Oct 24 '15 at 00:18
  • I supose you are discovering services of the connected peripheral and requesting for characteristics of these services, isn't it? Do you stop scanning when you connect to peripheral? – nigelman Oct 26 '15 at 01:43

1 Answers1

2

I recently run into the same problem. The only solution I found was to restart the bluetooth (turn bluetooth off and turn it back on).

In my case, it was a change in the bluetooth device (restarting it in DFU mode) that always caused this problem, so I ended up showing an alert to the user to restart the bluetooth. Listened for centralManagerDidUpdateState:'s Powered Off and than Powered back On state event to determine if the restart was done.

Kádi
  • 2,586
  • 14
  • 22