有什么方法可以在不连接的情况下监控发现的 BLE 外围设备?
Any way to monitor discovered BLE peripherals without connecting?
如果发现的 BLE 外围设备移出范围或以其他方式消失在视线之外,是否有任何方法可以收到通知?我正在使用 rxBleClient.scanBleDevices()
构建广告区域中的设备列表,但在将此列表发送到主应用程序之前,我想确保所有设备仍然可以访问。这样做的最佳方法是什么?
您可以创建一个 Transformer
来收集扫描的设备并发出一个列表,该列表会保持最新,具体取决于最近看到设备的时间。
香草 Android 扫描 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;
相同的 API 可通过 RxBleClient.scanBleDevices(ScanSettings, ScanFilter...)
获得
CALLBACK_TYPE_FIRST_MATCH
和 CALLBACK_TYPE_MATCH_LOST
是可以放入 ScanSettings
的标志。
触发 CALLBACK_TYPE_MATCH_LOST
的超时时间约为 10 秒。这可能表示某个特定设备已不在 range/available。
罗伯特,这可能不是您所期望的,但请将其作为示例。我的 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 }
}
}
如果发现的 BLE 外围设备移出范围或以其他方式消失在视线之外,是否有任何方法可以收到通知?我正在使用 rxBleClient.scanBleDevices()
构建广告区域中的设备列表,但在将此列表发送到主应用程序之前,我想确保所有设备仍然可以访问。这样做的最佳方法是什么?
您可以创建一个 Transformer
来收集扫描的设备并发出一个列表,该列表会保持最新,具体取决于最近看到设备的时间。
香草 Android 扫描 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;
相同的 API 可通过 RxBleClient.scanBleDevices(ScanSettings, ScanFilter...)
CALLBACK_TYPE_FIRST_MATCH
和 CALLBACK_TYPE_MATCH_LOST
是可以放入 ScanSettings
的标志。
触发 CALLBACK_TYPE_MATCH_LOST
的超时时间约为 10 秒。这可能表示某个特定设备已不在 range/available。
罗伯特,这可能不是您所期望的,但请将其作为示例。我的 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 }
}
}