manolofdez / AsyncBluetooth

A small library that adds concurrency to CoreBluetooth APIs.
MIT License
160 stars 30 forks source link

setNotifyValue - How to correctly stop notifications? #27

Closed theedov closed 1 year ago

theedov commented 1 year ago

Hello,

How do I stop the notifications correctly? My current situation is that when I try to enable - disable - enable notifications, I then get duplicated values. More times I disable/enable, more duplicates I get. So basically if I disable/enable 5 times, I then get the same 5 values returned from the characteristicValueUpdatedPublisher at the same time.

Here is my code:

Start notifications:

            if let service = peripheral.discoveredServices?.first(where: { $0.uuid == Constants.Device.deviceUUID.cbuuid }) {
                try await peripheral.discoverCharacteristics([Constants.Device.sensorUUID.cbuuid], for: service)
                self.characteristic = service.discoveredCharacteristics?.first(where: {
                    $0.uuid == Constants.Device.sensorUUID.cbuuid
                })

                if let characteristic {
                    try await peripheral.setNotifyValue(true, for: characteristic)
                    trackingState = .trackingEnabled
                }
            } 

            for await characteristic in peripheral.characteristicValueUpdatedPublisher.values {
                guard characteristic.uuid == Constants.Device.sensorUUID.cbuuid else { return }
                let value: Int? = try? characteristic.parsedValue()
            }

Stop notifications:

        guard let peripheral = peripheral, let characteristic, characteristic.isNotifying == true else { return }

        do {
            try await peripheral.setNotifyValue(false, for: characteristic)
            trackingState = .trackingDisabled
        } catch {
            showErrorBanner(error)
        }

Note: I also tried try await peripheral.setNotifyValue(<#T##enabled: Bool##Bool#>, forCharacteristicWithUUID: <#T##UUID#>, ofServiceWithUUID: <#T##UUID#>).

theedov commented 1 year ago

Hmm, I think I have to use combine here and cancel the characteristicValueUpdatedPublisher manually.

notification = peripheral.characteristicValueUpdatedPublisher.sink(receiveValue: { characteristic in
                guard characteristic.uuid == Constants.Device.sensorUUID.cbuuid else { return }
                let parsedValue: Int? = try? characteristic.parsedValue()
            })

...

notification?.cancel()