IOBluetooth 的问题

问题描述

我有几个关于 IOBluetooth 框架的问题,如下所列。

  1. 我目前有一台运行 Big Sur v11.1 的 MacBook Pro(13 英寸,2018 年),当我打电话询问并尝试查找附近的设备时,它经常失败并且无法始终如一地工作。另一方面,我有第二台 MacBook Pro(13 英寸,2015 年)运行 Mojave v10.14.6,它具有完全相同的功能并且每次都可以正常工作。我还一直在使用 blueutil 命令行工具:https://github.com/toy/blueutil 以及 PyBluez:https://github.com/pybluez/pybluez 进行测试,发现我的第二台运行 Mojave 的 MacBook 总是能找到附近的设备,而运行 Big Sur 的 MacBook 则无法做到这一点。你知道这是因为框架的潜在更新还是我的笔记本电脑运行 Big Sur 有问题?

  2. 我试图将 L2CAPChannel 从我的第一台笔记本电脑打开到第二台,反之亦然,但在 IOBluetoothDevice 对象(我已正确实例化)上调用 openL2CAPChannelSync 似乎永远不会返回 kIOReturnSuccess。我在这里也做错了吗?我附上了我在下面使用的代码片段(其中我删除了其他设备的 addressstring)。

import IOBluetooth
import PlaygroundSupport

class ChannelDelegate : IOBluetoothL2CAPChannelDelegate {

    func l2capChannelOpenComplete(_ l2capChannel: IOBluetoothL2CAPChannel!,status error: IOReturn) {
        print("Channel Opened!")
    }

}

var remoteDevice = IOBluetoothDevice(addressstring: ***deviceString***)
print((remoteDevice?.name ?? "nil") as String)

remoteDevice?.openConnection()
var connection = remoteDevice?.isConnected()
print(connection!)

var channelPtr: AutoreleasingUnsafeMutablePointer<IOBluetoothL2CAPChannel?>?
var success = remoteDevice?.openL2CAPChannelSync(channelPtr,withPSM: 0x0000,delegate: ChannelDelegate())
print(success == kIOReturnSuccess)

PlaygroundPage.current.needsIndefiniteExecution = true

解决方法

关于第二点,我修复了代码,贴在下面。问题在于 Apple 的文档指出该对象是使用函数调用 openL2CAPChannelSync 实例化的,但事实并非如此。您需要先实例化对象,然后将引用传递给您实例化的对象。鉴于 IOBluetooth API 上的示例很少,希望这可以为人们节省一些时间。

import IOBluetooth
import PlaygroundSupport

class ChannelDelegate : IOBluetoothL2CAPChannelDelegate {

    func l2capChannelOpenComplete(_ l2capChannel: IOBluetoothL2CAPChannel!,status error: IOReturn) {
        print("Channel Opened!")
    }

}

var remoteDevice = IOBluetoothDevice(addressString: ***deviceString***)
print((remoteDevice?.name ?? "nil") as String)

remoteDevice?.openConnection()
var connection = remoteDevice?.isConnected()
print(connection!)

var channel: IOBluetoothL2CAPChannel? = IOBluetoothL2CAPChannel()
var success = remoteDevice?.openL2CAPChannelSync(&channel,withPSM: 0x0000,delegate: ChannelDelegate())
print(success == kIOReturnSuccess)

PlaygroundPage.current.needsIndefiniteExecution = true