troystribling / BlueCap

iOS Bluetooth LE framework
MIT License
714 stars 114 forks source link

Connection callbacks not called if scanning is not stopped #54

Closed arrix closed 7 years ago

arrix commented 7 years ago

Unlike in the examples where stopScanning() is called before connect(), I'd like to keep scanning for other devices after making a connection.

In didConnectPeripheral(), connectionPromise? was nil because the Peripheral in _discoveredPeripherals[] was overwritten in didDiscoverPeripheral() which always creates a new Peripheral instance.

Is it possible to keep objects in _discoveredPeripherals[] stable? Update the properties instead of replacing the object.

This will allow holding references to the Peripheral object.

I'm happy to discuss more or even coding.

troystribling commented 7 years ago

In your scan options is CBCentralManagerScanOptionAllowDuplicatesKey=true? If you set it to false there will only be one discovery event and the peripheral will not be overwritten.

https://developer.apple.com/reference/corebluetooth/cbcentralmanagerscanoptionallowduplicateskey

Overwriting the discovered peripheral is there so RSSI can be monitored without connecting. RSSI is returned with the discovered CBPeripheral.

If you need your scan to run with CBCentralManagerScanOptionAllowDuplicatesKey=true you can have two CentralManagers. One for discovery and the other for connecting. This is done in the BlueCap app here https://github.com/troystribling/BlueCap/blob/master/Examples/BlueCap/BlueCap/Central/PeripheralsViewController.swift.

When you discover a peripheral the second CentralManager can use retrievePeripherals(withIdentifiers identifiers: [UUID]) -> [Peripheral] to fetch the discovered peripheral and connect.

https://github.com/troystribling/BlueCap/blob/master/BlueCapKit/Central/CentralManager.swift#L240-L244

arrix commented 7 years ago

Thanks for replying!

Yes I was using CBCentralManagerScanOptionAllowDuplicatesKey=true. Having two CentralManagers is one solution.

Can we update RSSI (and perhaps other information) on the existing Peripheral object? iOS itself gives the same CBPeripheral instance every time in centralManager(_:didDiscover:advertisementData:rssi:). It could make things easier if we keep the instance stable too.

troystribling commented 7 years ago

I just pushed a change to master that changes the behavior. Do you want to check it out?

arrix commented 7 years ago

I tried your change and made some other updates. See pull request #55

troystribling commented 7 years ago

I added a check for inconsistency between UUID and CBPeripheral reference and throw an error. I do not see the point in replacing the CBPeripheral since the I feel the condition is very unlikely.

arrix commented 7 years ago

Thanks! I just returned from vacation today. Will try your new change once it's pushed.

troystribling commented 7 years ago

The change is currently on the release-0.5.0 branch. I will do a new pod release next week.