bluejay icon indicating copy to clipboard operation
bluejay copied to clipboard

Fix handling of peripheral name

Open DrAma999 opened this issue 5 years ago • 3 comments

This issue is related about how iOS caches peripherals and how it updates its cached data one the device is connected. Once you do scan iOS caches all the peripherals names in advertising packets along with a the assigned UUIDs. Once you connect to a peripheral the name property is updated with the name in the GAP (sometime advertising name and GAP name could differ due to size reason). Cached names and peripheral identifiers persist until a full erase on the iOS devices. If another device changes the name of peripheral some inconsistency could arise.

The connection mechanism on Bluejay works on peripheral identifier, once we pass the peripheral identifier extracts the UUID, call the method retrievePeripherals and obtain the related CBPeripheral. This peripheral is passed to a Connection operation, that also set the connectingPeripheral property.

Once the device is connected in the didConnect delegate method of CBCentralManager the connectingPeripheral is passed to the connectedPeripheral, basically avoiding any possibility to the name to be updated also on the bluejay side, since the connectingPeripheral represent the old state.

DrAma999 avatar Jun 28 '19 10:06 DrAma999

Hi @nbrooke, just want to get your input on this issue too. I think it makes sense, and it seems like the more reliable thing to do instead of connectedPeripheral = connectingPeripheral, is to create another Peripheral instance based on the "slightly newer/potentially different" CBPeripheral we get back from centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)

sakuraehikaru avatar Oct 01 '19 23:10 sakuraehikaru

I made a branch and I'm testing this approach, unfortunately it seems that caching on iOS is more complex than that. It seems that even if you change the connectedPeripheral with the new one, the name in the GAP is still the old, it requires 3 connections and disconnections to be updated. There are a lot of posts on SO and Apple forums about it, it seems that is due to the firmware on the embedded hardware. The iOS cache only updates if the embedded device exposes some specific flag or characteristic. https://forums.developer.apple.com/thread/19381 https://forums.developer.apple.com/thread/76339 https://forums.developer.apple.com/thread/72343

I've spoken with our firmware engineer, still didn't have enough time to dig on it, but on his side everything seems fine,

DrAma999 avatar Oct 02 '19 06:10 DrAma999

Using the newer peripheral does seem like a totally reasonable change, even if it doesn't actually fix this.

From.a quick glance at the referenced threads, it looks like there also may be a delegate method related to this stuff that we probably should be implementing: https://developer.apple.com/documentation/corebluetooth/cbperipheraldelegate/1518801-peripheraldidupdatename

I also think that the device name is just a regular characteristic (see "Device Name" here: https://www.bluetooth.com/specifications/gatt/characteristics/), so another option might be to just read that directly rather than trusting the one in the peripheral (Not 100% sure if that'd be appropriate to do automatically at the Bluejay level, I don't love the ideal of it fetching a characteristic automatically on each connect, but if fetching that does solve the problem, we could totally provide a utility function for fetching the name from the characteristic, and keep our own cached copy of it rather than returning what is in the peripheral)

nbrooke avatar Oct 02 '19 17:10 nbrooke