Передача данных по каналу CoreBluetooth / L2CAP - PullRequest
0 голосов
/ 16 января 2019

При попытке установить передачу данных в CoreBluetooth по каналу L2CAP. У меня проблемы. На отправляющей стороне у меня есть эта функция стрельбы по нажатию кнопки:

@objc func sendL2CAPInfo() {
    print(#function)
    let value = "Hello L2Cap Stream data...",
    data = Data(value.utf8)
    outPutStream.open()
    print("outPutStream -> \(outPutStream.debugDescription)")
    let bytesWritten = data.withUnsafeBytes { outPutStream.write($0, maxLength: data.count) }
    print("bytesWritten = \(bytesWritten)")
}

Когда он выполняется, я вижу это в консоли отладки Xcode:

sendL2CAPInfo()
outPutStream -> Optional(<__NSCFOutputStream: 0x282969b00>)
bytesWritten = 26

На принимающей стороне у меня есть эта функция, также стрельба по нажатию кнопки:

@objc func receiveL2CAPInfo() {
    print(#function)
    let bufLength = 10
    var buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufLength)
    inPutStream.open()
    let bytesRead = inPutStream.read(buffer, maxLength: bufLength)
    print("bytesRead = \(bytesRead)")
}

Все еще на принимающей стороне, у меня также есть этот код:

// StreamDelegate protocol implementation.

func stream(_ aStream: Stream,
            handle eventCode: Stream.Event) {
    print(#function)
    if aStream == inPutStream {print("Input-Stream")}
    if aStream == outPutStream {print("Output-Stream")}

    switch eventCode {
    case Stream.Event.hasBytesAvailable:
        print("Stream.Event.hasBytesAvailable")
        receiveL2CAPInfo()
    case Stream.Event.hasSpaceAvailable:
        print("Stream.Event.hasSpaceAvailable")
    case Stream.Event.openCompleted:
        print("Stream.Event.openCompleted")
    case Stream.Event.endEncountered:
        print("Stream.Event.endEncountered")
    case Stream.Event.errorOccurred:
        print("Stream.Event.errorOccurred")
    default:
        print("Stream.Event.SOME-OTHER-THING-HAPPENED")
    }
}

При запуске принимающего приложения (во время работы отправляющего приложения) я вижу это в консоли отладки Xcode:

centralManagerDidUpdateState
centralManager(_:didDiscover:advertisementData:rssi:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-17 13:16:37.168700+0900 CBL2CAPCh_Central[857:127305] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
stream(_:handle:)
Input-Stream
Stream.Event.hasBytesAvailable
receiveL2CAPInfo()
bytesRead = 0
stream(_:handle:)
Input-Stream
Stream.Event.endEncountered

На отправляющей стороне кажется, что все идет как положено, записано 26 байтов. С другой стороны, на принимающей стороне мы не видим входящие 26 байтов.

Что не так? Раньше я никогда не использовал L2CAP канал, поэтому наверняка я делаю что-то нехорошее, но понятия не имею, что. Буду очень признателен за любую рекомендацию о том, что проверять или где смотреть.

..... После более глубокого изучения этой темы, вот еще немного информации.

Вот код для функции потока (_: handle :):

func stream(_ aStream: Stream,
            handle eventCode: Stream.Event) {
    print(#function)
    if aStream == inPutStream {print("Input-Stream")}
    if aStream == outPutStream {print("Output-Stream")}

    if (aStream != inPutStream) && (aStream != outPutStream)
    {print("Some-other-Stream")}

    switch eventCode {
    case Stream.Event.hasBytesAvailable:
        print("Stream.Event.hasBytesAvailable")
    case Stream.Event.hasSpaceAvailable:
        print("Stream.Event.hasSpaceAvailable")
    case Stream.Event.openCompleted:
        print("Stream.Event.openCompleted")
    case Stream.Event.endEncountered:
        print("Stream.Event.endEncountered")
    case Stream.Event.errorOccurred:
        print("Stream.Event.errorOccurred")
        if let error = aStream.streamError {
            print("Error:\n\t\(error.localizedDescription)")
        }
    default:
        print("Stream.Event.SOME-OTHER-THING-HAPPENED")
    }
}

Вот что можно увидеть в отладчике после запуска центрального приложения, прежде чем пытаться что-либо написать:

centralManagerDidUpdateState
centralManager(_:didDiscover:advertisementData:rssi:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-18 13:32:14.840892+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
stream(_:handle:)
Input-Stream
Stream.Event.hasBytesAvailable
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
stream(_:handle:)
Output-Stream
Stream.Event.hasSpaceAvailable
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-18 13:32:28.521320+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
stream(_:handle:)
Input-Stream
Stream.Event.hasBytesAvailable
stream(_:handle:)
Output-Stream
Stream.Event.hasSpaceAvailable
2019-01-18 13:32:28.523746+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] No known channel matching peer <CBPeripheral: 0x281bc4a00, identifier = D73B08A0-E9BB-483B-8078-4A7F992E7565, name = Michel’s iPad, state = connected> with psm 192
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-18 13:32:38.948090+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
2019-01-18 13:32:38.949889+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] No known channel matching peer <CBPeripheral: 0x281bc4a00, identifier = D73B08A0-E9BB-483B-8078-4A7F992E7565, name = Michel’s iPad, state = connected> with psm 192
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-18 13:32:49.278142+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
2019-01-18 13:32:49.280093+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] No known channel matching peer <CBPeripheral: 0x281bc4a00, identifier = D73B08A0-E9BB-483B-8078-4A7F992E7565, name = Michel’s iPad, state = connected> with psm 192
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-18 13:32:59.739338+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
2019-01-18 13:32:59.741111+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] No known channel matching peer <CBPeripheral: 0x281bc4a00, identifier = D73B08A0-E9BB-483B-8078-4A7F992E7565, name = Michel’s iPad, state = connected> with psm 192
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-18 13:33:10.567965+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
2019-01-18 13:33:10.569722+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] No known channel matching peer <CBPeripheral: 0x281bc4a00, identifier = D73B08A0-E9BB-483B-8078-4A7F992E7565, name = Michel’s iPad, state = connected> with psm 192
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-18 13:33:21.404162+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
2019-01-18 13:33:21.406243+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] No known channel matching peer <CBPeripheral: 0x281bc4a00, identifier = D73B08A0-E9BB-483B-8078-4A7F992E7565, name = Michel’s iPad, state = connected> with psm 192
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-18 13:33:32.147567+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
2019-01-18 13:33:32.148884+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] No known channel matching peer <CBPeripheral: 0x281bc4a00, identifier = D73B08A0-E9BB-483B-8078-4A7F992E7565, name = Michel’s iPad, state = connected> with psm 192
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-18 13:33:42.788001+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
2019-01-18 13:33:42.789921+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] No known channel matching peer <CBPeripheral: 0x281bc4a00, identifier = D73B08A0-E9BB-483B-8078-4A7F992E7565, name = Michel’s iPad, state = connected> with psm 192
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
2019-01-18 13:33:53.734140+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 431
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
2019-01-18 13:33:53.736063+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] No known channel matching peer <CBPeripheral: 0x281bc4a00, identifier = D73B08A0-E9BB-483B-8078-4A7F992E7565, name = Michel’s iPad, state = connected> with psm 192
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
2019-01-18 13:34:04.231561+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 436
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
2019-01-18 13:34:14.861939+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 436
centralManager(_:didDisconnectPeripheral:error:)
centralManager(_:didConnect:)
peripheral(_:didOpen:error:)
stream(_:handle:)
Some-other-Stream
Stream.Event.hasSpaceAvailable
stream(_:handle:)
Output-Stream
Stream.Event.openCompleted
stream(_:handle:)
Input-Stream
Stream.Event.openCompleted
stream(_:handle:)
Some-other-Stream
Stream.Event.hasBytesAvailable
2019-01-18 13:34:25.472075+0900 CBL2CAPCh_Central[571:80355] [CoreBluetooth] WARNING: Unknown error: 436

1 Ответ

0 голосов
/ 17 января 2019

Вместо того, чтобы пытаться открыть поток при нажатии кнопки, вы должны открыть поток, когда канал подключен. Затем можно использовать событие потокового делегата hasBytesAvailable, чтобы определить, есть ли байты для чтения.

Важно запланировать потоки в текущем цикле выполнения.

Например, чтобы открыть потоки на CBCentral:

func peripheral(_ peripheral: CBPeripheral, didOpen channel: CBL2CAPChannel?, error: Error?) {
    if let error = error {
        print("Error opening l2cap channel - \(error.localizedDescription)")
        return
    }
    guard let channel = channel else {
        return
    }
    print("Opened channel \(channel)")
    self.channel = channel
    channel.inputStream.delegate = self
    channel.outputStream.delegate = self
    print("Opened channel \(channel)")
    channel.inputStream.schedule(in: RunLoop.current, forMode: .default)
    channel.outputStream.schedule(in: RunLoop.current, forMode: .default)
    channel.inputStream.open()
    channel.outputStream.open()
}

А затем обработать полученные данные:

 func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
     switch eventCode {
        case Stream.Event.openCompleted:
            print("Stream is open")
        case Stream.Event.endEncountered:
            print("End Encountered")
        case Stream.Event.hasBytesAvailable:
            print("Bytes are available")
            if let iStream = aStream as? InputStream {
                let bufLength = 1024
                let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufLength)
                let bytesRead = iStream.read(buffer, maxLength: bufLength)
                print("bytesRead = \(bytesRead)")
                if let string = String(bytesNoCopy: buffer, length: bytesRead, encoding: .utf8, freeWhenDone: false) {
                    print("Received data: \(string)")
                }
            }
        case Stream.Event.hasSpaceAvailable:
            print("Space is available")
        case Stream.Event.errorOccurred:
            print("Stream error")
        default:
            print("Unknown stream event")
    }
}

Мой полный рабочий пример доступен здесь: https://github.com/paulw11/L2CapDemo

...