Skip to content
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

Using asFlow() from no.nordicsemi.android.ble.ktx #605

Open
natalyabl opened this issue Jan 31, 2025 · 4 comments · May be fixed by #607
Open

Using asFlow() from no.nordicsemi.android.ble.ktx #605

natalyabl opened this issue Jan 31, 2025 · 4 comments · May be fixed by #607

Comments

@natalyabl
Copy link

natalyabl commented Jan 31, 2025

Hi!
Last year we upgraded our Android app to use android.ble.ktx:2.7.5 to communicate with sensors we develop. We are working on upgrading to 2.9.0 but there are a few extra changes we have to do on our side.
Recently we've noticed an increase on delays in the communication and discovered that most of the time some packages are going missing.

We decided to use asFlow to get notifications from the sensor like this:

        notificationsFlow = setNotificationCallback(readCharacteristic).asFlow()
        enableNotifications(readCharacteristic).enqueue()

which we call in the initialize function.

In our app, we scan for the sensor, connect to it and then we request some information from the sensor which we collect from notificationsFlow. For some reason, the first packet we are expecting, sometimes is not received. Is there an specific way of doing this?
I haven't found an example using asFlow(), could somebody maybe send across an example or is it not reliable to be use as it's annotated with @ExperimentalCoroutinesApi?

Thanks!
Nbl

@natalyabl natalyabl changed the title Using asFlow() fro no.nordicsemi.android.ble.ktx Using asFlow() from no.nordicsemi.android.ble.ktx Jan 31, 2025
@philips77
Copy link
Member

Hello,
You're using it correctly. Let me check if there are no bugs on our side.

@philips77
Copy link
Member

Could you do an experiment?
Have a look at this code:

fun ValueChangedCallback.asFlow(): Flow<Data> = callbackFlow {
// Make sure the callbacks are called without unnecessary delay.
setHandler(null)
with { _, data ->
trySend(data)
}
awaitClose {
// There's no way to unregister the callback from here.
with { _, _ -> }
}
}

In line 28 we're calling trySend(..), which may fail, if the buffer is full (last event wasn't consumed). I suspect that this is the reason why you would loose packets. The documentation for callbackFlow says:

A channel with the default buffer size is used. Use the buffer operator on the resulting flow to specify a user-defined value and to control what happens when data is produced faster than consumed, i. e. to control the back-pressure behavior.

Could you add buffer(capacity = ...) on the resulting flow and check if it helps?

Another option would be to replace trySend(data) with trySendBlocking(data), which block the sender when the buffer is full. If you have the library added as a module from source, could you modify the source and test it?

@philips77 philips77 linked a pull request Feb 4, 2025 that will close this issue
@philips77
Copy link
Member

Could you try the PR made and

  1. Check if number of lost packets dropped to 0
  2. Paste LogCat logs if it didn't

@natalyabl
Copy link
Author

Hi!
thanks for your quick reply!
I've tried the PR and it seems to be working alright but I also noticed a few other problems with our implementation that I had to change.
I'll try both trySend and trySendBlock with the new implementation and come back to you.
Thanks a lot for your help!
Nbl

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants