Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Bluetooth: CBPeripheral disconnects every ~10 seconds

I am seeing a weird bug in iOS 8.3 and am wondering if anyone else is seeing the same thing.

I have an iPad Air (in Central mode) and an iPhone 6 (in Peripheral mode) in very close proximity.

  • My CBCentralManager is initialized with a serial background queue and the CBCentralManagerOptionRestoreIdentifierKey option
  • The manager starts scanning for peripherals using the CBCentralManagerScanOptionAllowDuplicatesKey: true option
  • Within centralManager:didDiscoverPeripheral: I check against a list of peripherals that are already discovered:
let connect: () -> () = {
  peripheral.delegate = self
  self.devices[peripheral.identifier.UUIDString] = peripheral
  self.manager.connectPeripheral(peripheral, options: nil)
}

if let device = devices[peripheral.identifier.UUIDString] {
  if device.peripheral.state == .Disconnected {
    connect()
  }
} else if peripheral.state == .Disconnected {
  connect()
}
  • Once connected, I discover services and characteristics.

The peripheral now disconnects after about 10 seconds, is immediately discovered again and connects again. 10 seconds later this procedure repeats itself.

Is this a bug or am I doing something wrong here?

I have also tried to directly subscribe to a characteristic on the peripheral, but this did not seem to change anything.

like image 983
desktop Avatar asked Apr 18 '15 09:04

desktop


1 Answers

It is an expected behaviour. Bluetooth was designed to consume very little amount of energy so it drops the connection as soon as possible. Also at least in iOS 7 it was not necessary to rediscover peripheral device - you was able to reconnect to already discovered device after disconnection. I am pretty sure it is also true for iOS 8. The recommended way to work with BLE if you do not need a permanent connection is:

  1. Discover
  2. Connect
  3. Read/write all you need as soon as possible
  4. Setup timer
  5. When timer fires go to point 2

If you need a permanent connection (for example you need to take data about heart rate in real time) you should subscribe for characteristic with - setNotifyValue:forCharacteristic:

When you enable notifications for characteristic’s value, the peripheral calls the peripheral:didUpdateNotificationStateForCharacteristic:error: method of its delegate object to notify your app when the characteristic’s value changes. Because it is the peripheral that chooses when to send an update, your app should be prepared to handle them as long as notifications or indications remain enabled.

like image 55
Avt Avatar answered Oct 20 '22 16:10

Avt