Polidea / RxBluetoothKit

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

Characteristics with same CBUUID in different services #410

Open lynx56 opened 2 years ago

lynx56 commented 2 years ago

Describe the bug I have two services in one peripheral. Service A
55AA0148-0001-55AA-1461-227D5E1F4C35 with characteristic tx: 55AA0001-0001-55AA-1461-227D5E1F4C35

Service B 55AA0248-0001-55AA-1461-227D5E1F4C35 with similar characteristic tx: 55AA0001-0001-55AA-1461-227D5E1F4C35

When I try to observe both tx characteristics, I get only one notification To Reproduce

typealias ReadCharacteristic = Observable<Data>

public class DefaultCharacteristicsService {
    public let observeConnection: Observable<Bool>
    private let bag = DisposeBag()
    private let peripheral: Peripheral
    private var peripheralObserver: Observable<Peripheral> = .empty()
    private var peripheralSubscription: SerialDisposable

    public init(peripheral: Peripheral) {
        self.peripheral = peripheral
        observeConnection = peripheral.observeConnection()
        peripheralSubscription = SerialDisposable()
        peripheralSubscription.disposed(by: bag)
    }

    public func start() -> Observable<Bool> {
        peripheralObserver = peripheral.establishConnection().share(replay: 1, scope: .forever)
        peripheralSubscription.disposable = peripheralObserver.subscribe()
        return peripheral.observeConnection()
    }

    public func stop() {
        peripheral.manager.manager.cancelPeripheralConnection(peripheral.peripheral)
        peripheralSubscription.disposable.dispose()
    }

    public func observeCharacteristic(service: GATTService) -> ReadCharacteristic {
        characteristic(service: service)
            .flatMap {
                $0.characteristic.properties.contains(.notify) ||
                    $0.characteristic.properties.contains(.indicate) ? $0.observeValueUpdateAndSetNotification() : $0.readValue().asObservable()
            }
            .compactMap { $0.characteristic.value }
            .debug("observeCharacteristic \(service) characteristic")
    }

    private func characteristic(service: GATTService) -> Observable<Characteristic> {
        peripheralObserver
            .filter { $0.isConnected }
            .flatMap {
                $0.discoverServices([service.serviceCBUUID])
            }
            .asObservable()
            .flatMap { Observable.from($0) }
            .flatMap {
               $0.discoverCharacteristics([service.characteristicCBUUID])
            }
            .asObservable()
            .flatMap { Observable.from($0) }
    }
}
func test(peripheral: Peripheral) {
        let service = DefaultCharacteristicsService(peripheral: peripheral)
        service.start()

        service.observeCharacteristic(service: .init(characteristicCBUUID: CBUUID(string: "55AA0001-0001-55AA-1461-227D5E1F4C35"),
                                                     serviceCBUUID: CBUUID(string: "55AA0148-0001-55AA-1461-227D5E1F4C35"))).subscribe(onNext: {
            print($0.debugDescription)
        }, onError: {
            print($0.localizedDescription)
        }).disposed(by: bag)

        service.observeCharacteristic(service: .init(characteristicCBUUID: CBUUID(string: "55AA0001-0001-55AA-1461-227D5E1F4C35"),
                                                     serviceCBUUID: CBUUID(string: "55AA0248-0001-55AA-1461-227D5E1F4C35"))).subscribe(onNext: {
            print($0.debugDescription)
        }, onError: {
            print($0.localizedDescription)
        }).disposed(by: bag)
}

It print events in first subscription

Expected behavior It print events in different subscriptions

Probably problem is here (CharacteristicNotificationManager): https://ibb.co/MCkFKtz

Environment:

Thank you for your amazing job!