-
Notifications
You must be signed in to change notification settings - Fork 96
Fix iOS Bluetooth read operation suspension issue #875
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
First off, thanks for the thorough explanation and PR! Unfortunately, I think this will adversely effect the Android implementation, which already does a similar comparison. Ultimately, we should lean on the overridden equality check, but fix it to properly compare by their UUIDs (as you mentioned). Unfortunately, unlike Android (which provides an instance ID for characteristics), Core Bluetooth exposes no such API, so if two different characteristics exist with the same UUID (I admit, this is very unlikely, but it does not violate the spec) then our equality check should properly see them as not equal.
|
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Ok, I am running into some challenges with the instance ID approach. I'll look into it further in the coming days and keep you updated. |
@rafaelfrancisco-dev can you elaborate on this? It seems that some libraries perform It is possible either approach should work? Without knowing the implementation of Simply comparing UUIDs seems insufficient to me, since 2 characteristics can technically have the same UUID (which is why Android provides |
To give you context, this problem started by our need to connect to a device that has two Device Information services (there is an issue outside our control where we can't override the default service already being advertised by the used hardware and opted to create a new service with the same exact UUID's, this, while an ugly solution, doesn't seem to be explicitly forbidden by the BLE spec). So to get the correct service we iterate the discovered services and characteristics and get the last one matching the UUID for the characteristic we need at the moment. val discoveredServices = services
.filterNotNull()
.first()
val infoServiceUuid = Uuid.service("device_information")
val modelCharUuid = Uuid.characteristic("model_number_string")
val modelCharacteristics = discoveredServices.flatMap { service ->
service.characteristics.filter { char ->
char.serviceUuid == infoServiceUuid && char.characteristicUuid == modelCharUuid
}
}
val lastModelChar = modelCharacteristics.lastOrNull()
?: throw IllegalStateException("No readable characteristic found for $modelCharUuid")
val model = read(lastModelChar)On Android devices this code snippet works perfectly, on iOS however the read would suspend indefinitely due to equality check failing on the when statement I deleted on this PR: eventCharacteristic is DiscoveredCharacteristic && characteristic is DiscoveredCharacteristic ->
eventCharacteristic == characteristicThe eventCharacteristic is a DiscoveredCharacteristic but the equality check would fail in the eventCharacteristic == characteristic check, which I can only surmise it fails due to being a new instance (since when we compare by UUID's the check is valid). |
|
Thanks for the clarification. Makes sense. I'll follow up soon. |
|
Apologies, I fell ill and am just now feeling better. I'll take another look at this in the next day or two. |
|
No need to apologize, take your time. In the meantime we've been using the fork, so there is no rush at all. |
As iOS may return new instances on each delegate response we cannot use object identity here, and we also cannot use solely UUID as some devices have duplicates. I'm wondering if the solution is to uniqify by enumeration which is the approach we settled on in Topaz browser |
@rafaelfrancisco-dev Thanks for being understanding/patient. ❤️ I've looked into this a lot more, and discussed with my colleagues — being that Core Bluetooth provides neither instance IDs nor source code; it is difficult to know the best approach to workaround Core Bluetooth's limitations. We have some ideas of possible workarounds1 but I'd really like to perform some thorough testing prior to committing to workarounds. As such, I plan to get #51 in a usable state (which I'm actively working on) before being able to resume work on this issue. Footnotes
|
|
Is there any update on this? We currently run into the same issue that our code works perfectly fine on Android, but on iOS the observing does not work. We are now also using a fork for now, but we'd like to use the official implementation as soon as possible again. Another idea which came to our mind was to offer a method to observe on all characteristics, then the filtering could be done on the caller side - what do you think about that? We also would like to support for this topic, but we want to clarify with you first what your preferred solution would look like. |
|
@fgroeger I understand that using a fork can be cumbersome. I had hoped to get to this sooner, but work projects have taken much of my time and I haven't been able to give as much time to Kable as I would like. Hopefully I'll find some time soon, but in the mean time, I've created #1017 to provide a workaround ( When set to |
|
Great! That will help us probably. I will test it in our scenario and let you know. Thanks for the quick response! |
|
It works fine for us, thank you! 🚀 |
|
This solution also works on my end. |
Description
This pull request addresses an issue where Bluetooth read operations would suspend indefinitely on iOS devices due to an overly strict characteristic comparison in our event handling logic.
Problem
In our characteristic event handling, we were performing an identity comparison between two
DiscoveredCharacteristicobjects. On iOS, the system creates new instances of characteristic objects during operations, resulting in different object references despite representing the same logical Bluetooth characteristic. This identity check prevented read operations from completing successfully. This issue may be related to improper implementation of the library code on our side, but the current fix resolves the problem without negatively impacting existing functionality.Solution
Removed the redundant identity comparison condition, allowing the code to properly compare characteristics by their UUIDs rather than by object reference. This ensures that characteristics are matched based on their logical identity rather than memory location.