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

问题描述 投票:1回答:2

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

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

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

ios bluetooth-lowenergy core-bluetooth gatt
2个回答
0
投票

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

希望有所帮助。


0
投票

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

不幸的是,在didConnect中没有CBPeripheralManagerDelegate方法。如果您打算使用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)
    }

    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.