繁体   English   中英

iOS CoreBluetooth:GAP外围设备和GATT客户端?

[英]iOS CoreBluetooth: GAP Peripheral and GATT Client?

我们的系统包括一个带遥控装置的主设备。 主要设备是GAP Central和GATT Server。 远程控制单元通过BLE进行通告和连接,其中远程是GAP外围设备和GATT客户端。 当按下遥控器上的按钮时,它会将按钮状态特征写入GATT服务器。

我们想要编写一个iOS应用程序来充当和替换遥控器。 iOS CoreBluetooth是否可以作为GAP外设运行,同时也是GATT客户端? 应用程序必须作为外围设备进行广告,然后在连接后进行服务发现。 应用程序按钮将对主设备的GAP Central GATT服务器上的特征执行写入请求。

我们的配置与GATT DB通常位于GAP外设上的标准BLE模型略有不同。 但在我们的情况下,将主设备的设置存储在遥控器中是没有道理意义的。 iOS是否足够灵活以支持此配置?

只是为了澄清:你在谈论BLE服务请求。 不幸的是,CoreBluetooth只支持一个方向的服务请求,即iOS设备是GAP Central,另一个GAP Peripheral可以在iOS设备上发现GATT服务器。 这基本上是Pebble用来访问媒体控制( Apple Media Service )和通知( Apple Notification Center Service )的附件。 您将在CBCentralManagerScanOptionSolicitedServiceUUIDsKey上找到特殊字典键CBCentralManagerScanOptionSolicitedServiceUUIDsKey以支持上述方案,但CBCentralManagerScanOptionSolicitedServiceUUIDsKey上没有相应的支持您的方案。

希望有所帮助。

尽管许多组合都是有效的,但看起来CoreBluetooth会结合GAP和GATT角色。 因此,即使您的iOS应用程序将自己宣传为BLE外围设备,您也可以使用CBCentralManager连接回中央设备。 您可以使用retrieveConnectedPeripherals(withServices :)retrievePeripherals(withIdentifiers :)来查找中央设备,而不是像在中央应用程序中那样进行扫描。

不幸的是, CBPeripheralManagerDelegate中没有didConnect方法。 如果您要使用retrievePeripherals(withIdentifiers:)您需要添加虚拟服务和特性,并让您的中央设备在连接后访问该特性。 当您收到didReceiveReaddidSubscribeTo事件,可以将其重新连接到request.central.identifier 使用retrieveConnectedPeripherals(withServices:)更简单,但它在我的测试中并没有始终如一地返回中央设备。

retrieveConnectedPeripherals(withServices :)示例

import CoreBluetooth

// A GATT client for an iOS App that operates as a BLE Peripheral. CoreBluetooth requires using a CBCentralManager
// to use remote GATT services, but we don't have to actually scan for the remote device.
class GattClient: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
    // Replace with your service UUIDs
    let remoteServiceUUIDs = [CBUUID(string: "FACE")]
    var centralManager: CBCentralManager!
    var remoteDevice: CBPeripheral? = nil
    var timer: Timer? = nil

    override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if (central.state == .poweredOn) {
            // There's no `didConnect` event we can listen for, so poll for connected devices.
            timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block: findConnectedDevice)
        }
    }

    func findConnectedDevice(timer: Timer) {
        // Don't scan, just connect to the device already connected to us offering the right services.
        print("Searching for connected devices...")
        let connectedPeripherals = centralManager.retrieveConnectedPeripherals(withServices: remoteServiceUUIDs)
        print("Devices found: \(connectedPeripherals.count)")

        if (connectedPeripherals.count == 1) {
            remoteDevice = connectedPeripherals[0]
            print("Connecting...")
            centralManager.connect(remoteDevice!, options: nil)

            timer.invalidate()
        }
    }

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        print("Discovering services...")
        peripheral.delegate = self
        peripheral.discoverServices(remoteServiceUUIDs)
    }

    ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM