BLE中央iOS应用应该何时读取加密特性?

时间:2015-08-03 14:03:12

标签: ios bluetooth-lowenergy

我有一个iOS应用程序,它是我控制固件的外围设备的核心。一个类似的Android应用程序工作正常,能够连接到外围设备,发现服务,明确绑定,并读取加密的特征。

然而,在iOS上,CoreBluetooth API中没有明确的绑定。我的工作基础是,如果我想要结合,我应该只读取一个加密的特性,以强制发生粘合。

什么时候适合这样做?如果我在发现我想要阅读的特征时这样做,在这个函数中......

func peripheral(peripheral: CBPeripheral!, didDiscoverCharacteristicsForService service: CBService!, error: NSError!)

...我从未收到外围设备的回调:didUpdateValueForCharacteristic。我相信,在这一点上阅读一个未加密的特征确实有用。

[编辑]

这是我的CBPeripheralDelegate实现的代码。

import CoreBluetooth
import CoreLocation

class BluetoothPeripheralController: NSObject, CBPeripheralDelegate {

    private var _peripheral: CBPeripheral!
    var peripheral: CBPeripheral! {
        get {
            return self._peripheral
        }
        set {
            if self._peripheral != nil {
                self._peripheral = nil
            }

            self._peripheral = newValue

            if self._peripheral != nil {
                self.peripheralDidChange(newValue)
            }
        }
    }

    private var notificationCenter: NSNotificationCenter = {
        return NSNotificationCenter.defaultCenter()
    }()

    private var testModeCharacteristic: CBCharacteristic?

    private var voltageCharacteristic: CBCharacteristic?

    private var firmwareLoggingCharacteristic: CBCharacteristic?

    static let voltageDidChangeNotification = "voltageDidChangeNotification"

    static let testModeDidChangeNotification = "testModeDidChangeNotification"

    static let bonded = "bonded"

    static let firmwareLoggingDidChangeNotification = "firmwareLoggingDidChangeNotification"

    func peripheralDidChange(peripheral: CBPeripheral) {
        peripheral.delegate = self
    }

    func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: NSError!) {
        if error != nil {
            log.error("Error: \(error)")
            return
        }

        for service in peripheral.services {
            log.verbose("Discovering characteristics for service: \(BleService().lookup(service.UUID))")

            peripheral.discoverCharacteristics(nil, forService: service as! CBService)
        }
    }

    // Hold on to characteristic instances so we can read/write/notify on them later.
    func peripheral(peripheral: CBPeripheral!, didDiscoverCharacteristicsForService service: CBService!, error: NSError!) {
        if let chars = service.characteristics as? [CBCharacteristic] {
            log.verbose("* \(BleService().lookup(service.UUID))")

            for char in chars {
                log.verbose("** \(BleCharacteristic().lookup(char.UUID))")

                if char.UUID.isEqual(BleCharacteristic.voltageCharacteristicUUID) {
                    voltageCharacteristic = char
                }

                if char.UUID.isEqual(BleCharacteristic.testModeCharacteristicUUID) {
                    testModeCharacteristic = char

                    log.verbose("Reading value for test mode.")

                    // Reading any encrypted value here does NOT result in a callback to peripheral:didUpdateValueForCharacteristic.
                    peripheral.readValueForCharacteristic(char)
                }

                if char.UUID.isEqual(BleCharacteristic.nordicNrfUartRxUUID) {
                    firmwareLoggingCharacteristic = char
                }
            }
        }
    }

    func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {
        if error != nil {
            log.verbose("Error on value: \(error)")
            return
        }

        let data: NSData = characteristic.value

        log.verbose("Got value \(data) for characterisitc \(BleCharacteristic().lookup(characteristic.UUID))")

        switch characteristic.UUID {
        case BleCharacteristic.voltageCharacteristicUUID:
            var voltage: Float = 0.0

            data.getBytes(&voltage, length: sizeof(Float))

            log.debug("Voltage: \(voltage)")

            // The map view is interested in this.
            self.notificationCenter.postNotificationName(BluetoothPeripheralController.voltageDidChangeNotification, object: self, userInfo: ["voltage": NSNumber(float: voltage)])

        case BleCharacteristic.testModeCharacteristicUUID:
            log.debug("Test mode: \(data). We are now bonded.")

            self.notificationCenter.postNotificationName(BluetoothPeripheralController.bonded, object: self, userInfo: nil)

        default:
            log.debug("Unknown characteristic UUID: \(characteristic.UUID)")
        }
    }

    func peripheral(peripheral: CBPeripheral!, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {
        if error != nil {
            log.verbose("Error updating notification state: \(error)")
            return
        }

        switch characteristic.UUID {
        case BleCharacteristic.nordicNrfUartRxUUID:
            log.verbose("Notification state change on firmware logging. Now notifying: \(characteristic.isNotifying)")

        default:
            log.verbose("Unhandled characteristic: \(characteristic.description)")
        }
    }

    // Read/write
    func readTestMode() {
        if testModeCharacteristic == nil {
            log.warning("Trying to read test mode before we have a characterisitc instance.")

            return
        }

        // Calls back to peripheral:didUpdateValueForCharacteristic.
        peripheral.readValueForCharacteristic(testModeCharacteristic)
    }

}

2 个答案:

答案 0 :(得分:1)

使用服务的didDiscoverCharacteristicsForService属性确保characteristics中存在所需的特征。

当您尝试在绑定之前读取字符时,您的外围设备会返回身份验证错误。如果你需要对它进行操作,错误将出现在didUpdateValueForCharacteristic中,但仅错误就会触发绑定。

来自Bluetooth Accessory Design Guidelines

  

如果出于安全原因,配件需要保税关系   对于Central,外设应该拒绝使用ATT请求   适当时,身份验证错误代码不足。

答案 1 :(得分:0)

原来可以在peripheral:didDiscoverCharacteristicsForService期间读取一个特征值,而且我没有得到回调的唯一原因是iOS已经缓存了之前的绑定,但外围设备已经拥有了它自己的一面债券擦除。

解决方案是以下两者之一或两者:a)转到iOS设置应用程序并“忘记”外围设备和b)重新启动手机。