【发布时间】:2019-01-04 00:35:02
【问题描述】:
我有以下使用RxAndroidBle 的简单 BLE 设备设置过程的用例:
- 连接到 BLE 设备。
- 开始监听通知特性并设置解析器来解析每个传入的通知。然后解析器将使用
PublishSubject发布解析后的数据。 - 执行写入到写入特性(协商安全连接)。
- 等待解析器
PublishSubject传递来自设备的解析响应 - 公钥(它通过通知特性到达,作为对我们写入的响应)。 - 对写入特征执行另一次写入(将连接设置为安全)。
- 发送
Completable说明该过程是否成功完成。
现在我的解决方案(不起作用)如下所示:
deviceService.connectToDevice(macAddress)
.andThen(Completable.defer { deviceService.setupCharacteristicNotification() })
.andThen(Completable.defer { deviceService.postNegotiateSecurity() })
.andThen(Completable.defer {
parser.notificationResultSubject
.flatMapCompletable { result ->
when (result) {
DevicePublicKeyReceived -> Completable.complete()
else -> Completable.error(Exception("Unexpected notification parse result: ${result::class}"))
}
}
})
.andThen(Completable.defer { deviceService.postSetSecurity() })
还有DeviceService 类:
class DeviceService {
/**
* Observable keeping shared RxBleConnection for reuse by different calls
*/
private var connectionObservable: Observable<RxBleConnection>? = null
fun connectToDevice(macAddress: String): Completable {
return Completable.fromAction {
connectionObservable =
rxBleClient.getBleDevice(macAddress)
.establishConnection(false)
.compose(ReplayingShare.instance())
}
}
fun setupCharacteristicNotification(): Completable =
connectionObservable?.let {
it
.switchMap { connection ->
connection.setupNotification(UUID_NOTIFICATION_CHARACTERISTIC)
.map { notificationObservable -> notificationObservable.doOnNext { bytes -> parser.parse(bytes) }.ignoreElements() }
.map { channel ->
Observable.merge(
Observable.never<RxBleConnection>().startWith(connection),
channel.toObservable()
)
}
.ignoreElements()
.toObservable<RxBleConnection>()
}
.doOnError { Timber.e(it, "setup characteristic") }
.take(1).ignoreElements()
} ?: Completable.error(CONNECTION_NOT_INITIALIZED)
fun postNegotiateSecurity(): Completable {
val postLength = negotiateSecurity.postNegotiateSecurityLength()
val postPGK = negotiateSecurity.postNegotiateSecurityPGKData()
return connectionObservable?.let {
it.take(1)
.flatMapCompletable { connection ->
postLength
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
.doOnError { Timber.e(it, "post length") }
.flatMap {
postPGK
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
.doOnError { Timber.e(it, "post PGK") }
}
.take(1).ignoreElements()
}
} ?: Completable.error(CONNECTION_NOT_INITIALIZED)
}
fun postSetSecurity(): Completable =
connectionObservable?.let {
it.take(1)
.flatMapCompletable { connection ->
negotiateSecurity.postSetSecurity()
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
.take(1).ignoreElements()
}
} ?: Completable.error(CONNECTION_NOT_INITIALIZED)
}
private fun RxBleConnection.write(bytes: ByteArray): Single<ByteArray> =
writeCharacteristic(UUID_WRITE_CHARACTERISTIC, bytes)
问题是它卡在deviceService.postNegotiateSecurity() 中并且永远不会过去。我也没有在解析器中获得任何数据,所以我认为我错误地订阅了通知特性。
negotiateSecurity.postNegotiateSecurityLength() 和negotiateSecurity.postNegotiateSecurityPGKData() 是准备要发送的数据并将其作为Observable<SendFragment> 传递的方法。由于数据帧大小的限制,一帧可能会被编码为多个片段,然后由这些Observables 发出。
【问题讨论】:
标签: rx-java2 rxandroidble