[英]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:)
您需要添加虚拟服务和特性,并让您的中央设备在连接后访问该特性。 当您收到didReceiveRead
或didSubscribeTo
事件,可以将其重新连接到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.