RxJava2/RxAndroidBle: subscribe to Observable from side effects
I have the following use case of a simple BLE device setup process using RxAndroidBle:
- Connect to a BLE device.
- Start listening to notification characteristic and set up a parser to parse each incoming notification. Parser will then use a
PublishSubjectto publish parsed data. - Perform a write to write characteristic (negotiate secure connection).
- Wait for parser
PublishSubjectto deliver the parsed response from device - public key (which arrived through the notification characteristic as a response to our write). - Perform another write to the write characteristic (set connection as secure).
- Deliver a
Completablesaying if the process has completed successfully or not.
Right now my solution (not working) looks like this:
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() })
And the DeviceService class:
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)
The problem is that it gets stuck in deviceService.postNegotiateSecurity() and never gets past. I don't get any data in the parser as well, so I assume I'm incorrectly subscribing to the notification characteristic.
negotiateSecurity.postNegotiateSecurityLength() and negotiateSecurity.postNegotiateSecurityPGKData() are methods which prepare data to be sent and deliver it as Observable<SendFragment>. Because of data frame size limit, one frame might be encoded as several fragments, which are then emitted by these Observables.
rx-java2 rxandroidble
add a comment |
I have the following use case of a simple BLE device setup process using RxAndroidBle:
- Connect to a BLE device.
- Start listening to notification characteristic and set up a parser to parse each incoming notification. Parser will then use a
PublishSubjectto publish parsed data. - Perform a write to write characteristic (negotiate secure connection).
- Wait for parser
PublishSubjectto deliver the parsed response from device - public key (which arrived through the notification characteristic as a response to our write). - Perform another write to the write characteristic (set connection as secure).
- Deliver a
Completablesaying if the process has completed successfully or not.
Right now my solution (not working) looks like this:
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() })
And the DeviceService class:
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)
The problem is that it gets stuck in deviceService.postNegotiateSecurity() and never gets past. I don't get any data in the parser as well, so I assume I'm incorrectly subscribing to the notification characteristic.
negotiateSecurity.postNegotiateSecurityLength() and negotiateSecurity.postNegotiateSecurityPGKData() are methods which prepare data to be sent and deliver it as Observable<SendFragment>. Because of data frame size limit, one frame might be encoded as several fragments, which are then emitted by these Observables.
rx-java2 rxandroidble
add a comment |
I have the following use case of a simple BLE device setup process using RxAndroidBle:
- Connect to a BLE device.
- Start listening to notification characteristic and set up a parser to parse each incoming notification. Parser will then use a
PublishSubjectto publish parsed data. - Perform a write to write characteristic (negotiate secure connection).
- Wait for parser
PublishSubjectto deliver the parsed response from device - public key (which arrived through the notification characteristic as a response to our write). - Perform another write to the write characteristic (set connection as secure).
- Deliver a
Completablesaying if the process has completed successfully or not.
Right now my solution (not working) looks like this:
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() })
And the DeviceService class:
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)
The problem is that it gets stuck in deviceService.postNegotiateSecurity() and never gets past. I don't get any data in the parser as well, so I assume I'm incorrectly subscribing to the notification characteristic.
negotiateSecurity.postNegotiateSecurityLength() and negotiateSecurity.postNegotiateSecurityPGKData() are methods which prepare data to be sent and deliver it as Observable<SendFragment>. Because of data frame size limit, one frame might be encoded as several fragments, which are then emitted by these Observables.
rx-java2 rxandroidble
I have the following use case of a simple BLE device setup process using RxAndroidBle:
- Connect to a BLE device.
- Start listening to notification characteristic and set up a parser to parse each incoming notification. Parser will then use a
PublishSubjectto publish parsed data. - Perform a write to write characteristic (negotiate secure connection).
- Wait for parser
PublishSubjectto deliver the parsed response from device - public key (which arrived through the notification characteristic as a response to our write). - Perform another write to the write characteristic (set connection as secure).
- Deliver a
Completablesaying if the process has completed successfully or not.
Right now my solution (not working) looks like this:
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() })
And the DeviceService class:
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)
The problem is that it gets stuck in deviceService.postNegotiateSecurity() and never gets past. I don't get any data in the parser as well, so I assume I'm incorrectly subscribing to the notification characteristic.
negotiateSecurity.postNegotiateSecurityLength() and negotiateSecurity.postNegotiateSecurityPGKData() are methods which prepare data to be sent and deliver it as Observable<SendFragment>. Because of data frame size limit, one frame might be encoded as several fragments, which are then emitted by these Observables.
rx-java2 rxandroidble
rx-java2 rxandroidble
asked Nov 20 '18 at 16:53
Lukasz KalnikLukasz Kalnik
62
62
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Recap:
postNegotiateSecurity()is never completed
negotiateSecurity.postNegotiateSecurityLength()may emit one or more times
negotiateSecurity.postNegotiateSecurityPGKData()may emit one or more times
Analysis (omitted logs for readability):
it.take(1)
.flatMapCompletable { connection ->
postLength
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
.flatMap {
postPGK // may emit more than one value
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
}
.take(1) // first emission from the above `flatMap` will finish the upstream
.ignoreElements()
}
Every emission from postLength will start a characteristic write. Every succeeded write will start subscription to postPGK. If postLength will emit more than once — more subscriptions to postPGK will be made.
Every subscription to postPGK most likely will result in multiple emissions. Every emission will then be flatMapped to a characteristic write. Every write succeeded write will emit a value.
After the first emission from the above mentioned characteristic write the upstream will be disposed (because of .take(1) operator).
If the postNegotiateSecurity() is actually started it will also finish or error (given that both postLength and postPGK will emit at least one value) since there is no additional logic here.
Conclusion
postNegotiateSecurity() will most probably complete (but not in an intended manner) as the first packet from postPGK will finish it. I would assume that the peripheral expects full data before it will notify anything therefore it is waiting for the PGK to be fully transmitted which will not happen as shown above.
Logs from the application with RxBleLog.setLogLevel(RxBleLog.VERBOSE) set on could help with understanding of what actually happened.
Thanks for your answer! It turned out the main culprit wastake(1), which interrupted the connection. There were some other things wrong with my architecture here as well.
– Lukasz Kalnik
Jan 4 at 17:22
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53397824%2frxjava2-rxandroidble-subscribe-to-observable-from-side-effects%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Recap:
postNegotiateSecurity()is never completed
negotiateSecurity.postNegotiateSecurityLength()may emit one or more times
negotiateSecurity.postNegotiateSecurityPGKData()may emit one or more times
Analysis (omitted logs for readability):
it.take(1)
.flatMapCompletable { connection ->
postLength
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
.flatMap {
postPGK // may emit more than one value
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
}
.take(1) // first emission from the above `flatMap` will finish the upstream
.ignoreElements()
}
Every emission from postLength will start a characteristic write. Every succeeded write will start subscription to postPGK. If postLength will emit more than once — more subscriptions to postPGK will be made.
Every subscription to postPGK most likely will result in multiple emissions. Every emission will then be flatMapped to a characteristic write. Every write succeeded write will emit a value.
After the first emission from the above mentioned characteristic write the upstream will be disposed (because of .take(1) operator).
If the postNegotiateSecurity() is actually started it will also finish or error (given that both postLength and postPGK will emit at least one value) since there is no additional logic here.
Conclusion
postNegotiateSecurity() will most probably complete (but not in an intended manner) as the first packet from postPGK will finish it. I would assume that the peripheral expects full data before it will notify anything therefore it is waiting for the PGK to be fully transmitted which will not happen as shown above.
Logs from the application with RxBleLog.setLogLevel(RxBleLog.VERBOSE) set on could help with understanding of what actually happened.
Thanks for your answer! It turned out the main culprit wastake(1), which interrupted the connection. There were some other things wrong with my architecture here as well.
– Lukasz Kalnik
Jan 4 at 17:22
add a comment |
Recap:
postNegotiateSecurity()is never completed
negotiateSecurity.postNegotiateSecurityLength()may emit one or more times
negotiateSecurity.postNegotiateSecurityPGKData()may emit one or more times
Analysis (omitted logs for readability):
it.take(1)
.flatMapCompletable { connection ->
postLength
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
.flatMap {
postPGK // may emit more than one value
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
}
.take(1) // first emission from the above `flatMap` will finish the upstream
.ignoreElements()
}
Every emission from postLength will start a characteristic write. Every succeeded write will start subscription to postPGK. If postLength will emit more than once — more subscriptions to postPGK will be made.
Every subscription to postPGK most likely will result in multiple emissions. Every emission will then be flatMapped to a characteristic write. Every write succeeded write will emit a value.
After the first emission from the above mentioned characteristic write the upstream will be disposed (because of .take(1) operator).
If the postNegotiateSecurity() is actually started it will also finish or error (given that both postLength and postPGK will emit at least one value) since there is no additional logic here.
Conclusion
postNegotiateSecurity() will most probably complete (but not in an intended manner) as the first packet from postPGK will finish it. I would assume that the peripheral expects full data before it will notify anything therefore it is waiting for the PGK to be fully transmitted which will not happen as shown above.
Logs from the application with RxBleLog.setLogLevel(RxBleLog.VERBOSE) set on could help with understanding of what actually happened.
Thanks for your answer! It turned out the main culprit wastake(1), which interrupted the connection. There were some other things wrong with my architecture here as well.
– Lukasz Kalnik
Jan 4 at 17:22
add a comment |
Recap:
postNegotiateSecurity()is never completed
negotiateSecurity.postNegotiateSecurityLength()may emit one or more times
negotiateSecurity.postNegotiateSecurityPGKData()may emit one or more times
Analysis (omitted logs for readability):
it.take(1)
.flatMapCompletable { connection ->
postLength
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
.flatMap {
postPGK // may emit more than one value
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
}
.take(1) // first emission from the above `flatMap` will finish the upstream
.ignoreElements()
}
Every emission from postLength will start a characteristic write. Every succeeded write will start subscription to postPGK. If postLength will emit more than once — more subscriptions to postPGK will be made.
Every subscription to postPGK most likely will result in multiple emissions. Every emission will then be flatMapped to a characteristic write. Every write succeeded write will emit a value.
After the first emission from the above mentioned characteristic write the upstream will be disposed (because of .take(1) operator).
If the postNegotiateSecurity() is actually started it will also finish or error (given that both postLength and postPGK will emit at least one value) since there is no additional logic here.
Conclusion
postNegotiateSecurity() will most probably complete (but not in an intended manner) as the first packet from postPGK will finish it. I would assume that the peripheral expects full data before it will notify anything therefore it is waiting for the PGK to be fully transmitted which will not happen as shown above.
Logs from the application with RxBleLog.setLogLevel(RxBleLog.VERBOSE) set on could help with understanding of what actually happened.
Recap:
postNegotiateSecurity()is never completed
negotiateSecurity.postNegotiateSecurityLength()may emit one or more times
negotiateSecurity.postNegotiateSecurityPGKData()may emit one or more times
Analysis (omitted logs for readability):
it.take(1)
.flatMapCompletable { connection ->
postLength
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
.flatMap {
postPGK // may emit more than one value
.flatMapSingle { connection.write(it.bytes.toByteArray()) }
}
.take(1) // first emission from the above `flatMap` will finish the upstream
.ignoreElements()
}
Every emission from postLength will start a characteristic write. Every succeeded write will start subscription to postPGK. If postLength will emit more than once — more subscriptions to postPGK will be made.
Every subscription to postPGK most likely will result in multiple emissions. Every emission will then be flatMapped to a characteristic write. Every write succeeded write will emit a value.
After the first emission from the above mentioned characteristic write the upstream will be disposed (because of .take(1) operator).
If the postNegotiateSecurity() is actually started it will also finish or error (given that both postLength and postPGK will emit at least one value) since there is no additional logic here.
Conclusion
postNegotiateSecurity() will most probably complete (but not in an intended manner) as the first packet from postPGK will finish it. I would assume that the peripheral expects full data before it will notify anything therefore it is waiting for the PGK to be fully transmitted which will not happen as shown above.
Logs from the application with RxBleLog.setLogLevel(RxBleLog.VERBOSE) set on could help with understanding of what actually happened.
answered Jan 3 at 16:35
Dariusz SewerynDariusz Seweryn
1,8921717
1,8921717
Thanks for your answer! It turned out the main culprit wastake(1), which interrupted the connection. There were some other things wrong with my architecture here as well.
– Lukasz Kalnik
Jan 4 at 17:22
add a comment |
Thanks for your answer! It turned out the main culprit wastake(1), which interrupted the connection. There were some other things wrong with my architecture here as well.
– Lukasz Kalnik
Jan 4 at 17:22
Thanks for your answer! It turned out the main culprit was
take(1), which interrupted the connection. There were some other things wrong with my architecture here as well.– Lukasz Kalnik
Jan 4 at 17:22
Thanks for your answer! It turned out the main culprit was
take(1), which interrupted the connection. There were some other things wrong with my architecture here as well.– Lukasz Kalnik
Jan 4 at 17:22
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53397824%2frxjava2-rxandroidble-subscribe-to-observable-from-side-effects%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown