Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read followed by write #383

Open
eddy93 opened this issue Sep 28, 2020 · 2 comments
Open

Read followed by write #383

eddy93 opened this issue Sep 28, 2020 · 2 comments

Comments

@eddy93
Copy link

eddy93 commented Sep 28, 2020

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
Copy link
Collaborator

minixT commented Oct 9, 2020

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
Copy link
Author

eddy93 commented Mar 9, 2021

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants