有没有连接可以监控发现的BLE外设的方法?

时间:2018-06-06 05:28:03

标签: android bluetooth-lowenergy rxandroidble

如果发现的BLE外围设备超出范围或以其他方式失去视线,是否有任何通知方式?我正在使用rxBleClient.scanBleDevices()来构建广告区域中的设备列表,但在将此列表发送到主应用程序之前,我想确保所有设备仍然可以访问。这样做的最佳方法是什么?

3 个答案:

答案 0 :(得分:1)

vanilla Android Scan API允许扫描回调类型为:

的BLE设备
/**
 * A result callback is only triggered for the first advertisement packet received that matches
 * the filter criteria.
 */
public static final int CALLBACK_TYPE_FIRST_MATCH = 2;

/**
 * Receive a callback when advertisements are no longer received from a device that has been
 * previously reported by a first match callback.
 */
public static final int CALLBACK_TYPE_MATCH_LOST = 4;

RxBleClient.scanBleDevices(ScanSettings, ScanFilter...)

可以使用相同的API

CALLBACK_TYPE_FIRST_MATCHCALLBACK_TYPE_MATCH_LOST是可以放入ScanSettings的标记。

触发CALLBACK_TYPE_MATCH_LOST之后的超时大约是10秒。这可能表示特定设备不再在范围/可用范围内。

答案 1 :(得分:0)

您可以创建一个Transformer来收集已扫描的设备并发出一个列表,该列表会保持最新状态,具体取决于最近看到该设备的时间。

答案 2 :(得分:0)

罗伯特,这可能不是你想象的那样,但把它作为一个例子。我的Transformer每当发生更改时都会发出一个项目列表,原因是扫描仪更新或驱逐发生(每秒检查一次)。

class RollingPairableDeviceReducer(
        private val systemTime: SystemTime,
        private val evictionTimeSeconds: Long,
        private val pairableDeviceFactory: PairableDeviceFactory
) : Observable.Transformer<ScannedDevice, List<PairableDevice>> {
    override fun call(source: Observable<ScannedDevice>): Observable<List<PairableDevice>> {
        val accumulator: MutableSet<PairableDevice> = Collections.synchronizedSet(mutableSetOf())
        return source
                .map { createPairableDevice(it) }
                .map { pairableDevice ->
                    val added = updateOrAddDevice(accumulator, pairableDevice)
                    val removed = removeOldDevices(accumulator)
                    added || removed
                }
                .mergeWith(checkEvictionEverySecond(accumulator))
                .filter { addedOrRemoved -> addedOrRemoved == true }
                .map { accumulator.toList() }
    }

    private fun createPairableDevice(scannedDevice: ScannedDevice)
            = pairableDeviceFactory.create(scannedDevice)

    private fun updateOrAddDevice(accumulator: MutableSet<PairableDevice>, emittedItem: PairableDevice): Boolean {
        val existingPairableDevice = accumulator.find { it.deviceIdentifier.hardwareId == emittedItem.deviceIdentifier.hardwareId }
        return if (existingPairableDevice != null) {
            accumulator.remove(existingPairableDevice)
            existingPairableDevice.updateWith(emittedItem)
            accumulator.add(existingPairableDevice)
            false
        } else {
            accumulator.add(emittedItem)
            true
        }
    }

    private fun checkEvictionEverySecond(collector: MutableSet<PairableDevice>): Observable<Boolean>
            = Observable.interval(1, TimeUnit.SECONDS)
            .map { removeOldDevices(collector) }

    private fun removeOldDevices(accumulator: MutableSet<PairableDevice>): Boolean {
        val currentTimeInMillis = systemTime.currentTimeInMillis()
        val evictionTimeMillis = TimeUnit.SECONDS.toMillis(evictionTimeSeconds)
        return accumulator.removeAll { (currentTimeInMillis - it.lastSeenTime) >= evictionTimeMillis }
    }
}