代码之家  ›  专栏  ›  技术社区  ›  Michel

使用Core蓝牙/L2CAP通道传输数据

  •  0
  • Michel  · 技术社区  · 7 年前

    尝试设置数据传入时 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 回复  |  直到 7 年前
        1
  •  1
  •   Paulw11    7 年前

    当点击一个按钮时,您不应该试图打开流,而应该在通道连接时打开流。然后可以使用流委托 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