Сканирование периферийных устройств BLE с помощью фильтра сканирования на основе рекламируемой услуги UUID - PullRequest
5 голосов
/ 06 ноября 2019

У меня есть пользовательское периферийное устройство BLE, которое объявляет данные следующим образом:

enter image description here

Другими словами, мое периферийное устройство BLE объявляет UUID службы, связанный суникальный идентификатор в данных о рекламируемых услугах, но он не добавляет этот UUID службы в список рекламируемых услуг, потому что, если я это сделаю, у меня не останется места в кадре BLE для добавления уровня заряда батареи, когда мне это понадобится.

На iOS я могу сканировать с помощью фильтра, основанного на UUID службы, и видеть мое периферийное устройство. Но в Android со следующим фильтром сканирования я не вижу свою периферию:

val scanSettingsBuilder = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setReportDelay(0L)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    scanSettingsBuilder
                .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
                .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
                .setNumOfMatches(ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)
}
bluetoothAdapter?.bluetoothLeScanner?.startScan(
    arrayListOf(ScanFilter.Builder().setServiceUuid(ParcelUuid(UUID.fromString("00004865-726f-6e54-7261-636b2d475053"))).build()),
    scanSettingsBuilder.build(),
    leScanCallback
)

У кого-нибудь есть более подробная информация о том, как работает фильтр сканирования на основе serviceUUID, и какие условия должны иметь периферийные устройства? встретиться, чтобы быть принятым фильтром?

1 Ответ

1 голос
/ 11 ноября 2019

Я понял, как заставить это работать ... вроде. Проблема в том, что мой фильтр был на serviceUuid, который, как я полагаю, просматривает периферийные устройства, которые рекламируют UUID в коллекции advertisedServices. Моя периферия объявляет UUID только как ключ в своем ассоциативном массиве serviceData, поэтому я переключился на фильтр serviceData следующим образом, и теперь я могу найти свое периферийное устройство:

AsyncTask.execute {
    val scanFilters = Settings.scannedBleServices.values.map {
        ScanFilter.Builder().setServiceData(it, null).build()
    }
    val scanSettingsBuilder = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setReportDelay(0L)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        scanSettingsBuilder
                .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
                .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
                .setNumOfMatches(ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)
    }
    bluetoothAdapter?.bluetoothLeScanner?.startScan(
            scanFilters,
            scanSettingsBuilder.build(),
            leScanCallback
    )
}

Проблема в том, чтотеперь фильтр слишком разрешительный, так как я получаю обратный вызов для всех периферийных устройств, даже без каких-либо serviceData, как если бы я вообще не указал фильтр. Может быть, это потому, что я передал null в качестве второго параметра setServiceData в фильтре, потому что я не знал, что еще добавить туда. И документация не совсем полезна.

Я предполагаю, что этого достаточно для сканирования в фоновом режиме (я еще не пробовал), но это будет иметь больше смысла, еслиЯ мог бы ограничить количество вызовов обратного вызова, и мне не нужно было фильтровать самому.

...