How to concatenate several subscriptions to a Disposable in RxSwift with RxBluetooth?

181 Views Asked by At

With RxBluetooth it never has been easier to connect to a CBPeripheral:

disposable = peripheral.establishConnection()
        .flatMap { $0.discoverServices([serviceId]) }.asObservable()
        .flatMap { Observable.from($0) }
        .flatMap { $0.discoverCharacteristics(nil)}.asObservable()
        .flatMap { Observable.from($0) }
        .flatMap { $0.readValue() }
        .subscribe(onNext: { characteristic in
            // At this point we have connected to the peripheral
            // Discovered the service with the id 'serviceId'
            // Discovered all the characteristics of the service
            // and this print will be triggered after reading each value

            print(Value read: characteristic.value)

        })

I would like to concatenate actions to the Peripheral, so when the subscription triggers, I know I have a validated peripheral.

The disposable will have concatenated actions, and will return a true if the actions were set successfully or an error.

Something like this:

disposable = peripheral.establishConnection()

        // Action 1: Let's validate the advertismentData, if it doesn't have the correct advertisement data, we trigger an error

        .flatMap { self.validateAdvertisementData($0) }
        // If there is no error we continue
        .flatMap { $0.discoverServices([serviceId]) }.asObservable()
        .flatMap { Observable.from($0) }
        .flatMap { $0.discoverCharacteristics(nil)}.asObservable()
        .flatMap { Observable.from($0) } 
        .flatMap { $0.readValue() }

        // Action 2: Let's validate the characteristics values, if a characteristic is missing a value we trigger an error

        .flatMap { self.validateInitialCharacteristics($0) }

        // If there is no error we continue by discovering the rest of the services of the peripheral

        // Action 3: We keep discovering services as this is a validated peripheral

        .flatMap { peripheral.discoverServices([healthServiceId, communicationServiceId]) }.asObservable()
        .flatMap { Observable.from(peripheral) }
        .flatMap { $0.discoverCharacteristics(nil)}.asObservable()
        .flatMap { Observable.from($0) } 
        .flatMap { $0.readValue() }

        //Action 4: Let's validate that we read the values and send an initialization packet to the peripheral   

        .flatMap { self.validateSubCharacteristics($0) }

        //Action 5: The values are valid, let's initialize the Peripheral

        .flatMap { self.initialize(peripheral) }

        //If we get a response, then it calls onNext.

        .subscribe(onNext: { Bool in
            // At this point we have connected to the peripheral
            // Discovered the service with the id 'serviceId'
            // Discover all the characteristics of the service
            // Read all values of these characteristics
            // Validated all the values
            // Made another discover for other services
            // Read the characteristics for those
            // Validated the values
            // Write to the peripheral
            // and this print will be triggered after the writing 

            print("Peripheral ready")

        }, onError: { Error in 

            print("Peripheral initialization failed")
        })

So the main idea is to concatenate different actions with RxSwift, and only get one response after all the actions have completed successfully, if not get one error.

Maybe I could use different subjects, or several subscriptions with only one disposable that I can dispose for disconnection, and concatenate them?

0

There are 0 best solutions below