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

Combining different filter types for scanner not working #627

Closed
jsundgren opened this issue Feb 1, 2024 · 16 comments
Closed

Combining different filter types for scanner not working #627

jsundgren opened this issue Feb 1, 2024 · 16 comments
Labels
android bug Something isn't working
Milestone

Comments

@jsundgren
Copy link

jsundgren commented Feb 1, 2024

Using: com.juul.kable:core:0.28.0

When using a combination of scan filters such as Service and NamePrefix it only finds the devices matching the NamePrefix.

Examples:

Finds all devices advertising with service ID 1 and 2.

private val scanner = Scanner {
        filters = listOf(
            Filter.Service(SERVICE_ID_1),
            Filter.Service(SERVICE_ID_2),
        )

        scanSettings = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
            .build()
    }

Finds only the devices with the name test and no devices advertising with the service ID 1 and 2.

private val scanner = Scanner {
        filters = listOf(
            Filter.Service(SERVICE_ID_1),
            Filter.Service(SERVICE_ID_2),
            Filter.NamePrefix("test"),
        )

        scanSettings = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
            .build()
    }

I am not sure if I am doing something wrong but the documentation for scanning states that you can mix the different filter types but it is not working for me, any help is appreciated and please ping if there is any other information you would like me to provide.

@twyatt
Copy link
Member

twyatt commented Feb 1, 2024

Thanks for the report!
Can you provide Kable logs with at least Events log level?

@jsundgren
Copy link
Author

We're currently not converting advertisements to peripherals during scanning but instead are using our local domain models. But I tried creating a peripheral when the flow returns the advertisements and added logging to it, but I am not receiving any logs and I am not really sure what I am looking for either? 😄

@jsundgren
Copy link
Author

Any updates on this @twyatt?

@twyatt
Copy link
Member

twyatt commented Feb 9, 2024

Can you provide logs when performing your scan?

You can create a Scanner with logging via:

Scanner {
    logging {
        level = Events // or `Data`
    }
    filters = ..
}

Do you also see the issue when you don't use scanSettings?

@jsundgren
Copy link
Author

jsundgren commented Feb 12, 2024

Remove ScanSettings does not change anything in the results.

Adding the logging with Data level gives me these logs:

With all filters added (two Service filters and one NamePrefix):

Kable/Scanner I  Starting scan with 3 filter(s)

With just the two Service filters:

Kable/Scanner I  Starting scan with 2 filter(s)

With one Service and one NamePrefix:

Kable/Scanner I  Starting scan with 2 filter(s)

@twyatt
Copy link
Member

twyatt commented Feb 12, 2024

I looked through the code some more and found what I believe to be the issue.

When a service filter is present, Kable is filtering services out before other filters, when it should be inspecting attributes in one pass (when multiple filters are specified).

I'll try to find some time soonish to get in a fix. Thanks again for the issue report!

@jsundgren
Copy link
Author

Cool, that would be a nice fix as we have to handle the scan filtering ourself at the moment and it's not ideal.
Thanks for looking into it!

@twyatt
Copy link
Member

twyatt commented Feb 21, 2024

@jsundgren this has been slated (internally) for our next sprint.
Work should begin in the coming weeks.

@twyatt twyatt added this to the 0.31.2 milestone Apr 18, 2024
@twyatt twyatt added bug Something isn't working android labels Apr 18, 2024
@twyatt twyatt changed the title Combining different filter types for scanner not working on Android Combining different filter types for scanner not working Apr 18, 2024
@twyatt
Copy link
Member

twyatt commented Jun 6, 2024

@jsundgren this has been slated (internally) for our next sprint. Work should begin in the coming weeks.

Sorry, this ended up being de-prioritized internally. I'll try to get it re-prioritized though.

@twyatt
Copy link
Member

twyatt commented Jul 29, 2024

@jsundgren can you try Kable 0.34.0 and let us know if this issue is resolved with the new scan filter DSL (#695)?

@twyatt twyatt closed this as completed Aug 8, 2024
@uruhans
Copy link

uruhans commented Aug 13, 2024

I have just tested 0.34.0 with 2xUUID + prefixed name as described in the READ.ME section.
Unfortunately it seems not to work.
(It did work with a single UUID + prefixed named, but that is not my usecase)


To have peripherals D1 and D3 emitted during a scan, you could use the following filters:

val scanner = Scanner {
    filters {
        match {
            services = listOf(uuidFrom("0000aa80-0000-1000-8000-00805f9b34fb")) // SensorTag
        }
        match {
            name = Filter.Name.Prefix("Ex")
        }
    }
}

@twyatt
Copy link
Member

twyatt commented Aug 13, 2024

@uruhans do you want to scan for devices that have both UUID 1 AND UUID 2, or are you wanting to search for devices that have UUID 1 OR UUID 2?

Some possible options (other variants also exist):

(UUID 1 and UUID 2) or Name.Prefix("Ex")

val scanner = Scanner {
    filters {
        match {
            services = listOf(uuidFrom("<uuid-1>"), uuidFrom("<uuid-2>"))
        }
        match {
            name = Filter.Name.Prefix("Ex")
        }
    }
}

(UUID 1 and Name.Prefix("Ex")) or (UUID 2 and Name.Prefix("Ex"))

val scanner = Scanner {
    filters {
        match {
            services = listOf(uuidFrom("<uuid-1>"))
            name = Filter.Name.Prefix("Ex")
        }
        match {
            services = listOf(uuidFrom("<uuid-2>"))
            name = Filter.Name.Prefix("Ex")
        }
    }
}

@uruhans
Copy link

uruhans commented Aug 14, 2024

I want to scan for both UUID 1 OR UUID 2 OR for Prefix name. So if any of these criterias are true then I want them in my list.

@twyatt
Copy link
Member

twyatt commented Aug 14, 2024

I want to scan for both UUID 1 OR UUID 2 OR for Prefix name. So if any of these criterias are true then I want them in my list.

Have you tried something along the lines of?:

val scanner = Scanner {
    filters {
        match {
            services = listOf(uuidFrom("<uuid-1>"))
        }
        match {
            services = listOf(uuidFrom("<uuid-2>"))
        }
        match {
            name = Filter.Name.Prefix("Ex")
        }
    }
}

@uruhans
Copy link

uruhans commented Aug 15, 2024

Thanks a lot for your help, that did the trick. Guess I was fooled by the listOf.

@twyatt
Copy link
Member

twyatt commented Aug 15, 2024

Thanks a lot for your help, that did the trick. Guess I was fooled by the listOf.

The way to think about it is:

  • everything within a match is AND'd (including listOf services)
  • each match is OR'd
filters {
    match {
        filter1 AND filter2 .. AND filterN
    }
    OR
    match {
        filter1 AND filter2 .. AND filterN
    }
    OR
    ..
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
android bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants