Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting Notifications on Characteristic results in Invalid Handle error

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".     } } 
like image 659
Suresh Avatar asked Aug 05 '14 13:08

Suresh


1 Answers

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.

like image 129
Kádi Avatar answered Sep 19 '22 12:09

Kádi