Polidea / RxBluetoothKit

iOS & OSX Bluetooth library for RxSwift
Apache License 2.0
1.41k stars 365 forks source link

Read followed by write #383

Open eddy93 opened 3 years ago

eddy93 commented 3 years ago

I have two characteristics one to read a notification and a characteristic to write. Thing is I want to write once reading is successful. Right now i’m discovering both characteristics, but with no use of the write one. How can I turn around my code to write to the write characteristic once the read is successful?

viewDidShow.subscribe(onNext: { [weak self] _ in
            guard let strongSelf = self else {return}
            manager.observeStateWithInitialValue()
                .filter {$0 == .poweredOn}
                .flatMap { _ in manager.scanForPeripherals(withServices: [CBUUID.Device.mainService])}
                .filter { $0.peripheral.identifier == userRepository.getSavedBottle()}
                .flatMap { $0.peripheral.establishConnection() }
                .flatMap { $0.discoverServices([CBUUID.Device.mainService]) }
                .flatMap { Observable.from($0) }
                .flatMap { $0.discoverCharacteristics([CBUUID.Device.readUUID, CBUUID.Device.writeUUID]) }
                .flatMap { Observable.from($0) }
                .flatMap { $0.observeValueUpdateAndSetNotification() }
                .subscribe(onNext: {
                    if $0.uuid == CBUUID.Device.readUUID {
                        let value = $0.value?.withUnsafeBytes({(rawPtr: UnsafeRawBufferPointer) in
                            return rawPtr.load(as: UInt64.self)
                        })
                        print(value)
                    }
                })
                .disposed(by: strongSelf.disposeBag)
        }).disposed(by: disposeBag)
minixT commented 3 years ago

Hi @eddy93,

you need to change your code a little. You need to save somehow write characteristic and use it after read operation. Here is an example how you can achieve this:

manager.observeStateWithInitialValue()
            .filter {$0 == .poweredOn} // wait until bluetooth is available
            .take(1)
            .flatMap { _ in manager.scanForPeripherals(withServices: [CBUUID.Device.mainService])} // find peripheral
            .filter { $0.peripheral.identifier == userRepository.getSavedBottle()}
            .take(1)
            .flatMap { $0.peripheral.establishConnection() } // connect to peripheral
            .flatMap { $0.discoverServices([CBUUID.Device.mainService]) } // discover services
            .flatMap { Observable.from($0) }
            .flatMap { $0.discoverCharacteristics([CBUUID.Device.readUUID, CBUUID.Device.writeUUID]) } // discover characteristics
            .flatMap { characteristics -> Observable<(read: Characteristic, write: Characteristic)> in
                // find read and write characteristics
                let readCharacteristic = characteristics.first(where: { $0.uuid == CBUUID.Device.readUUID})
                let writeCharacteristic = characteristics.first(where: { $0.uuid == CBUUID.Device.writeUUID})

                // if characteristics were not found emit an error
                guard let unwrappedReadCharacteristic = readCharacteristic,
                      let unwrappedWriteCharacteristic = writeCharacteristic else {
                    return .error(Error.characteristicsNotFound)
                }
                // start observing read characteristic and map result value to pass both read and write characteristic to the next block
                return unwrappedReadCharacteristic.observeValueUpdateAndSetNotification()
                    .map { (read: $0, write: unwrappedWriteCharacteristic) }
            }
            .flatMap { characteristisc -> Single<Characteristic> in
                // read value from read characteristic
                let value = characteristisc.read.value?.withUnsafeBytes({(rawPtr: UnsafeRawBufferPointer) in
                    return rawPtr.load(as: UInt64.self)
                })
                print(value)
                // after reading value, write new data to write characteristic
                return characteristisc.write.writeValue(Data(), type: .withResponse)
            }
            .subscribe(onNext: { _ in
                print("Write operation finished.")
            })
            .disposed(by: disposeBag)

I hope that this will help you.

eddy93 commented 3 years ago

Thanks that’s very helpful! Any idea how I can do it if I want to continuously: Write then read, write then read...