带有JustWorks绑定的iPhone和iPad之间的BLE连接

时间:2018-08-08 22:15:40

标签: ios swift bluetooth-lowenergy

我当前正在开发一个应用程序,该应用程序需要将数据从iPhone发送到iPad。我已经能够找到设备并通过同时使用CentralManagerPeriphiralManager进行连接。但是现在,它向我显示了一条消息,要求每次配对。但是,当我按下“ NO”选项时,它仍会通过使用JustWorks进行绑定(至少似乎是因为当我在设置中进入蓝牙时,它只会说“ iPad”,除此以外我看不到有关该设备的信息,当我断开连接时,它会从列表中完全消失。)

我想知道如何确保要求配对的弹出窗口根本不显示。我在某处读到禁用外围设备上的加密,但是当以iPad为外围设备时,我不确定如何执行此操作。我现在正在使用的代码如下所示(这是我第一次使用corebluetooth,现在我仍然在弄乱它,并试图掌握它的工作原理)。 / p>

import UIKit
import CoreBluetooth
import CoreLocation

class ViewController: UIViewController {
    @IBOutlet weak var receiveLabel: UILabel!
    @IBOutlet weak var sendButton: UIButton!

    var centralManager: CBCentralManager!
    var peripheralManager: CBPeripheralManager!
    var peripherals: [CBPeripheral] = []
    var keepScanning: Bool = false

    private var timerScanInterval: TimeInterval = 5
    static let SERVICE_UUID = CBUUID(string: "4DF91029-B356-463E-9F48-BAB077BF3EF5")
    static let RX_UUID = CBUUID(string: "3B66D024-2336-4F22-A980-8095F4898C42")
    static let RX_PROPERTIES: CBCharacteristicProperties = .write
    static let RX_PERMISSIONS: CBAttributePermissions = .writeable

    override func viewDidLoad() {
        super.viewDidLoad()

        centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
        peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
    }

}

extension ViewController {

    @IBAction func sendMessage(_ sender: UIButton) {
        for per in peripherals {
            centralManager.connect(per, options: nil)
        }

    }

    func updateAdvertisingData() {
        if peripheralManager.isAdvertising {
            peripheralManager.stopAdvertising()
        }

        peripheralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey: [ViewController.SERVICE_UUID], CBAdvertisementDataLocalNameKey: "Test"])
    }

    func initService() {

        let serialService = CBMutableService(type: ViewController.SERVICE_UUID, primary: true)
        let rx = CBMutableCharacteristic(type: ViewController.RX_UUID, properties: ViewController.RX_PROPERTIES, value: nil, permissions: ViewController.RX_PERMISSIONS)
        serialService.characteristics = [rx]

        peripheralManager.add(serialService)
    }

}

extension ViewController: CBCentralManagerDelegate {

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOn:
            centralManager.scanForPeripherals(withServices: [ViewController.SERVICE_UUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
            break
        default: break
        }
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        peripheral.discoverServices(nil)
        peripherals.append(peripheral)
    }

}

extension ViewController: CBPeripheralDelegate, CBPeripheralManagerDelegate {

    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        if peripheral.state == .poweredOn {
            initService()
            updateAdvertisingData()
        }
    }

    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        for service in peripheral.services! {
            peripheral.discoverCharacteristics(nil, for: service)
        }
    }

    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        for characteristic in service.characteristics! {
            let characteristic = characteristic as CBCharacteristic
            let message = "TestMessage".data(using: .utf8)
            peripheral.writeValue(message!, for: characteristic, type: CBCharacteristicWriteType.withResponse)
        }
    }

    func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
        for request in requests {
            if let value = request.value {
                let messageText = String(data: value, encoding: String.Encoding.utf8)
                receiveLabel.text = messageText
            }
            self.peripheralManager.respond(to: request, withResult: .success)
        }
    }

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        peripheral.delegate = self
        peripheral.discoverServices(nil)
    }

}

1 个答案:

答案 0 :(得分:2)

即使您仅搜索宣传特定服务的外围设备,但发现外围设备时,您都会致电

 peripheral.discoverServices(nil)

这将发现发现的外围设备(另一台iOS设备)上的所有服务,而不仅仅是您的特定服务。

然后,对于每项服务,您都会发现所有特征,对于发现的每项特征,您都会使用

 let message = "TestMessage".data(using: .utf8)
 peripheral.writeValue(message!, for: characteristic, type: CBCharacteristicWriteType.withResponse)

由于您已发现设备上所有服务的所有特征,然后尝试写入每个特征,因此如果其中任何特征需要加密,则将触发配对对话框。当您取消配对对话框时,该特定写入操作将失败,但是您的应用将继续运行(这就是为什么您在设置中看到连接的原因)。

您应该优化代码,以使其仅发现您感兴趣的特定服务,并仅尝试写入您的特征。这将防止触发配对对话框,因为您的特征不需要加密。