troystribling / BlueCap

iOS Bluetooth LE framework
MIT License
715 stars 115 forks source link

Write to characteristic after start receiveNotificationUpdates #83

Closed azlekov closed 5 years ago

azlekov commented 6 years ago

Hello, I'm developing app communicating with custom Bluetooth LE devices. We have already an Android app in production and the Bluetooth LE devices are working. Developing now iOS application I faced a strange behaviour, not sure exactly where is the trick.

I define profiles for the ProfileManager and using the example like this:

func activate() {
        let serviceUUID = CBUUID(string: NetGuard.DeviceInformationService.uuid)
        let readUUID = CBUUID(string: NetGuard.Read.uuid)
        let writeUUID = CBUUID(string: NetGuard.Write.uuid)

        let dataUpdateFuture = self.manager.whenStateChanges().flatMap { [unowned self] state -> FutureStream<Peripheral> in
            switch state {
            case .poweredOn:
                return self.manager.startScanning(forServiceUUIDs: [serviceUUID], capacity: 10)
            case .poweredOff:
                throw AppError.poweredOff
            case .unauthorized, .unsupported:
                throw AppError.invalidState
            case .resetting:
                throw AppError.resetting
            case .unknown:
                throw AppError.unknown
            }
            }.flatMap { [unowned self] peripheral -> FutureStream<Void> in
                self.manager.stopScanning()
                self.peripheral = peripheral
                return peripheral.connect(connectionTimeout: 10.0)
            }.flatMap { [unowned self] () -> Future<Void> in
                guard let peripheral = self.peripheral else {
                    throw AppError.unlikely
                }
                return peripheral.discoverServices([serviceUUID])
            }.flatMap { [unowned self] () -> Future<Void> in
                guard let peripheral = self.peripheral, let service = peripheral.services(withUUID: serviceUUID)?.first else {
                    throw AppError.serviceNotFound
                }
                return service.discoverCharacteristics([readUUID, writeUUID])
            }.flatMap { [unowned self] () -> Future<Void> in
                guard let peripheral = self.peripheral, let service = peripheral.services(withUUID: serviceUUID)?.first else {
                    throw AppError.serviceNotFound
                }
                guard let readChar = service.characteristics(withUUID: readUUID)?.first else {
                    throw AppError.dataCharactertisticNotFound
                }
                guard let writeChar = service.characteristics(withUUID: writeUUID)?.first else {
                    throw AppError.enabledCharactertisticNotFound
                }

                self.pingerReadCharacteristic = readChar
                self.pingerWriteCharacteristic = writeChar

                return writeChar.write(data: Data(bytes: Array(">".utf8)))
            }.flatMap { [unowned self] _ -> Future<[Void]> in
                return [self.pingerReadCharacteristic].compactMap { $0 }.map { $0.read(timeout: 10.0) }.sequence()
            }.flatMap { [unowned self] _ -> Future<Void> in
                guard let readChar = self.pingerReadCharacteristic else {
                    throw AppError.dataCharactertisticNotFound
                }
                return readChar.startNotifying()
            }.flatMap { [unowned self] () -> FutureStream<Data?> in
                guard let readChar = self.pingerReadCharacteristic else {
                    throw AppError.dataCharactertisticNotFound
                }
                return readChar.receiveNotificationUpdates(capacity: 10)
            }

        dataUpdateFuture.onSuccess { data in
            print("DATA:", data)
        }
    }
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:cancelPeripheralConnection(withTerminationStatus:):308: disconnecting name=Nordic_UART, uuid=B32E148D-9A29-9A28-B6D8-6A3F9FB793DD
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:cancelPeripheralConnection(withTerminationStatus:):308: disconnecting name=Nordic_UART, uuid=B32E148D-9A29-9A28-B6D8-6A3F9FB793DD
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/CentralManager.swift:startScanning(forServiceUUIDs:capacity:timeout:options:):180: 'com.alfastack.netguard' scanning UUIDs Optional([6E400001-B5A3-F393-E0A9-E50E24DCCA9E])
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/CentralManager.swift:didDisconnectPeripheral(_:error:):314: com.alfastack.netguard uuid=B32E148D-9A29-9A28-B6D8-6A3F9FB793DD, name=Optional("Nordic_UART"), error=nil
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/CentralManager.swift:centralManager(_:didDiscover:advertisementData:rssi:):282: advertisementData = ["kCBAdvDataServiceUUIDs": <__NSArrayM 0x280d30f00>(
6E400001-B5A3-F393-E0A9-E50E24DCCA9E
)
, "kCBAdvDataIsConnectable": 1, "kCBAdvDataLocalName": Nordic_UART]
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/CentralManager.swift:didDiscoverPeripheral(_:advertisementData:RSSI:):335: 'com.alfastack.netguard' uuid=B32E148D-9A29-9A28-B6D8-6A3F9FB793DD, name=Nordic_UART, RSSI=-46, Advertisements=["kCBAdvDataServiceUUIDs": <__NSArrayM 0x280d30f00>(
6E400001-B5A3-F393-E0A9-E50E24DCCA9E
)
, "kCBAdvDataIsConnectable": 1, "kCBAdvDataLocalName": Nordic_UART]
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/CentralManager.swift:stopScanningIfScanning():205: 'com.alfastack.netguard'
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:connect(connectionTimeout:capacity:):258: connect peripheral Nordic_UART', B32E148D-9A29-9A28-B6D8-6A3F9FB793DD
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:reconnectIfNotConnected:281: reconnect peripheral name=Nordic_UART, uuid=B32E148D-9A29-9A28-B6D8-6A3F9FB793DD
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:timeoutConnection:564: name = Nordic_UART, uuid = B32E148D-9A29-9A28-B6D8-6A3F9FB793DD, sequence = 1, timeout = 10.0
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/CentralManager.swift:didConnectPeripheral:307: 'com.alfastack.netguard' uuid=B32E148D-9A29-9A28-B6D8-6A3F9FB793DD, name=Optional("Nordic_UART")
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:didConnectPeripheral():462: uuid=B32E148D-9A29-9A28-B6D8-6A3F9FB793DD, name=Nordic_UART
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:discoverServices(_:timeout:):320:  Nordic_UART
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:didDiscoverServices(_:error:):392: peripheral name=Nordic_UART, peripheral uuid=B32E148D-9A29-9A28-B6D8-6A3F9FB793DD, service count 0
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:didDiscoverServices(_:error:):402: service uuid=6E400001-B5A3-F393-E0A9-E50E24DCCA9E, service name=Pinger Information, peripheral name=Nordic_UART, peripheral uuid=B32E148D-9A29-9A28-B6D8-6A3F9FB793DD
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Service.swift:discoverCharacteristics(_:timeout:):57: uuid=6E400001-B5A3-F393-E0A9-E50E24DCCA9E, name=Pinger Information
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:didDiscoverCharacteristicsForService(_:characteristics:error:):387: peripheral name=Nordic_UART, peripheral uuid=B32E148D-9A29-9A28-B6D8-6A3F9FB793DD, service name Pinger Information, characteristic count 2
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Service.swift:didDiscoverCharacteristics(_:error:):80: Discovered characterisc uuid=6E400003-B5A3-F393-E0A9-E50E24DCCA9E, characteristic name=RX Read, service name Pinger Information, service uuid 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Service.swift:didDiscoverCharacteristics(_:error:):80: Discovered characterisc uuid=6E400002-B5A3-F393-E0A9-E50E24DCCA9E, characteristic name=TX Write, service name Pinger Information, service uuid 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Service.swift:didDiscoverCharacteristics(_:error:):87: discovery success service name Pinger Information, service uuid 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Characteristic.swift:writeNext():397: write characteristic value=3e, uuid=6E400002-B5A3-F393-E0A9-E50E24DCCA9E
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:didWriteValueForCharacteristic(_:error:):438: uuid=6E400002-B5A3-F393-E0A9-E50E24DCCA9E, name=TX Write
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Characteristic.swift:didWrite:313: success:  uuid=6E400002-B5A3-F393-E0A9-E50E24DCCA9E, name=TX Write
/Users/lekov/Workspace/netguard-ios/Pods/BlueCapKit/BlueCapKit/Central/Peripheral.swift:timeoutConnection:571: connection timeout expired name = Nordic_UART, uuid = B32E148D-9A29-9A28-B6D8-6A3F9FB793DD, sequence = 1, current connectionSequence=1, state=2

It looks like writing to the input characteristic and after that enable notifying on the output characteristic doesn't report the result data. Also I change some Futures on the chain and I saw that the read was also successful, but again no data arrived.

On Android I checked that before writing and waiting for a response we first set the notification on the characteristic.

So can you give me some guidelines how can I rearrange the Futures in order to be able after connect and configure the notification on the input characteristic then to write on the output characteristic and wait for the data.

Thanks.

troystribling commented 5 years ago

Not sure I can do much without the device.

azlekov commented 5 years ago

I believe so, but afterwords I manage to implement it using CoreBluetooth and CentralManager, so we can close this issue now.