-
Notifications
You must be signed in to change notification settings - Fork 86
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
[Feature] Scanner: easy way to detect when device is no longer available #521
Comments
I'm reluctant to implement such a feature in Kable since I believe what should be considered "no longer available" comes down a lot to the needs of the app that is using Kable. Additionally, I think implementing such logic app-side should be fairly straight forward? Something to the effect of (pseudo code): // Fake advertisements identified as a single character.
val advertisements = MutableSharedFlow<Char>()
launch {
listOf(
'a', 'b', 'e', 'f', 'a', 'c', 'd', 'a', 'a', 'a', 'b', 'd', 'e', 'a', 'b', 'b', 'a',
'a', 'b', 'b', 'a', 'b', 'a', 'b', 'b', 'a', 'b', 'a', 'b', 'b', 'a', 'b', 'a', 'b',
).forEach {
advertisements.emit(it)
delay(1.seconds)
}
}
val mark1 = Clock.System.asTimeSource().markNow() + 10.24.seconds
val pass1 = advertisements.takeWhile { mark1.hasNotPassedNow() }.toSet()
val mark2 = Clock.System.asTimeSource().markNow() + 10.24.seconds
val pass2 = advertisements.takeWhile { mark2.hasNotPassedNow() }.toSet()
val noLongerAvailable = pass1 - pass2
println(noLongerAvailable) |
Thanks I'll experiment with this. If it does work, then what do you think about a utility method on advertisements like |
I'm reluctant to add such a utility method only because (as far as I understand) advertisement interval is customizable (on the peripheral side), so some firmware might use a more frequent interval while others use less, and The timeout could be configurable (and default to Ultimately, I appreciate the suggestion and always open to further discussion (I'm just cautious about growing the API unnecessarily). |
This approach works but there are a few complexities to keep in mind.
I went with an approach that looks something like this. My peripheral advertises every 250 ms so a 1 second chunk time was sufficient, and this approach does not require multiple separate scans: var visibleAddresses = emptySet<String>()
// any peripherals already connected from other app state
var connectedAddresses = setOf(...)
scanner.advertisements
// custom implementation
// see https://github.com/Kotlin/kotlinx.coroutines/issues/1302
.chunked(100, 1.seconds)
.map { it.associateBy { it.address } }
.distinctUntilChanged()
.collect { ads ->
val removed = lastAddresses - connectedAddresses - ads.keys
val added = ads.keys - lastAddresses
if (added.isNotEmpty() || removed.isNotEmpty()) {
lastAddresses = ads.keys
}
} If you are curious about my implementation of I don't feel this is trivial to do for an application consumer, so to me it makes sense to have some of this logic in Kable. However, I understand not wanting to expand the API surface. Feel free to close this issue. |
I see. You've definitely exposed more complexity than I had originally anticipated. I'll keep the issue open, as it allows others to discover the feature request and 👍 if they too would find it useful. That would at least gauge interest.
EDIT: I'd be happy to have extra features like this live in a separate module/artifact. |
@rocketraman if you're up for creating a PR, I'd be happy to have the feature live in a separate module/artifact that consumers can optionally pull into their projects. |
The Scanner should provide a way to determine when a device is no longer available, because it has been turned off or is no longer in range.
As I understand it, at least on Android, the right way to do this is to scan again, and determine from the new scan if any devices are no longer present relative to the previous scan.
See https://stackoverflow.com/questions/33033906/how-to-detect-when-a-ble-device-is-not-in-range-anymore.
The text was updated successfully, but these errors were encountered: