iOS Core蓝牙无法通过特征传输数据

时间:2018-12-06 15:40:45

标签: ios swift bluetooth bluetooth-lowenergy core-bluetooth

我正在创建一个iOS应用程序,该应用程序现在应该在两个iOS设备之间传输文本消息。 我想要/必须使用Core Bluetooth。一种设备成为外围设备,另一种成为中心设备。

使用一种服务包含两种特征(读1读1写)的外设设置没有问题。我使用LightBlue App连接到外围设备,我也可以看到其特性。

当我使用中央角色设备时,我会找到外围设备,可以连接并查看其特性。我将外围设备和特征都存储在自己的变量中,以后使用它们调用存储的外围设备的 writeValue(_ data:Data,用于特征:CBCharacteristic,类型:CBCharacteristicWriteType),不会抛出任何错误。 但是外围设备似乎未收到该消息,因为未调用其 didWriteValueFor didUpdateValueFor 方法。中央也不能订阅这些特征。

此外,当我使用外围设备更新其自身特性的值时,我对LightBlue App的检查也不成功,因为该值始终保持为空,并且中央设备当然也不会得到通知。

该应用程序发出的所有内容似乎都无法正常运行。似乎只有传入的数据(例如来自LightBlue App的数据)起作用。

有人遇到过类似的问题吗?我使用了许多不同的教程,并且完全按照那里的描述进行操作(因为到处都是相同的过程)。

谢谢!


我使用XCode版本10.1,在Swift中进行编码,并使用iPhone XS Max(iOS 12.1)和iPad Air 2(iOS 12.0)进行测试。


这是我的外围课程:

validation_steps

这是我的中心班级:

import CoreBluetooth
import UIKit

class BLEPeripheralManager: NSObject {

    //MARK:- Properties

    static let shared = BLEPeripheralManager()

    //just some delegates for other classes
    var peripheralDataReceiver: PeripheralDataReceiver?
    var peripheralChatDataReceiver: PeripheralChatDataReceiver?

    var peripheralManager: CBPeripheralManager

    var subscribedCentrals: [CBCentral] = []

    var readCharacteristic: CBMutableCharacteristic = {
        let uuidStringChar1 = UUIDs.characteristicUUID1
        let uuidChar1 = CBUUID(string: uuidStringChar1)
        let char = CBMutableCharacteristic(type: uuidChar1, properties: .read, value: nil, permissions: .readable)
        return char
    }()
    var writeCharacteristic: CBMutableCharacteristic = {
        let uuidStringChar2 = UUIDs.characteristicUUID2
        let uuidChar2 = CBUUID(string: uuidStringChar2)
        let char = CBMutableCharacteristic(type: uuidChar2, properties: .write, value: nil, permissions: .writeable)
        return char
    }()


    //MARK:- Private Methods

    private override init() {
        self.peripheralManager = CBPeripheralManager(delegate: nil, queue: nil)
        super.init()
        self.peripheralManager.delegate = self
    }

    private func setupManager() {
        let uuidStringServ = UUIDs.serviceUUID
        let uuidServ = CBUUID(string: uuidStringServ)

        let transferService = CBMutableService(type: uuidServ, primary: true)
        transferService.characteristics = [self.readCharacteristic, self.writeCharacteristic]

        self.peripheralManager.add(transferService)
    }

    private func teardownServices() {
        self.peripheralManager.removeAllServices()
    }

    private func clearSubscribers() {
        self.subscribedCentrals.removeAll()
    }

    //MARK:- Public Methods

    public func sendMessage(fromPeripheral peripheral: String, text: String) {
        if text.isEmpty { return }
        let chatMessage = ChatMsg(messageText: text, fromDevice: peripheral)
        let encoder = JSONEncoder()
        do {
            let data = try encoder.encode(chatMessage)
            print(self.readCharacteristic.uuid)
            if self.peripheralManager.updateValue(data, for: self.readCharacteristic, onSubscribedCentrals: nil) == false {
                print("Update from Peripheral failed (ReadCharacteristic)")
            } else {
                print("Message sent (ReadCharacteristic)")
            }
            if self.peripheralManager.updateValue(data, for: self.writeCharacteristic, onSubscribedCentrals: nil) == false {
                print("Update from Peripheral failed (WriteCharacteristic)")
            } else {
                print("Message sent (WriteCharacteristic)")
            }
        } catch {
            print("Error in encoding data")
        }
    }

    func startAdvertising() {
        let services = [CBUUID(string: UUIDs.serviceUUID)]
        let advertisingDict = [CBAdvertisementDataServiceUUIDsKey: services]

        self.peripheralManager.startAdvertising(advertisingDict)
    }

    public func stopAdvertising() {
        self.peripheralManager.stopAdvertising()
    }

    public func checkIfAdvertising() -> Bool {
        return self.peripheralManager.isAdvertising
    }
}


extension BLEPeripheralManager: CBPeripheralManagerDelegate {

    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        switch peripheral.state {
        case .poweredOff:
            print("Peripheral powered off")
            self.teardownServices()
            self.clearSubscribers()
        case .poweredOn:
            print("Peripheral powered on")
            self.setupManager()
        case .resetting:
            print("Peripheral resetting")
        case .unauthorized:
            print("Unauthorized Peripheral")
        case .unknown:
            print("Unknown Peripheral")
        case .unsupported:
            print("Unsupported Peripheral")
        }
    }

    //doesn`t get called
    func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
        for request in requests {
            if let value = request.value {
                if let messageText = String(data: value, encoding: String.Encoding.utf8) {
                    //
                }
            }
        }
    }

    //doesn`t get called
    func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
        var shouldAdd: Bool = true
        for sub in self.subscribedCentrals {
            if sub == central {
                shouldAdd = false
            }
        }
        if shouldAdd { self.subscribedCentrals.append(central) }
    }

}

1 个答案:

答案 0 :(得分:0)

我发现中央部分出了什么问题

发现后,我将外围设备及其特征存储在两个变量/元组中(writeTransferPeripheral和readTransferPeripheral)。我这样做是错误的:

self.writeTransferPeripheral?.peripheral = peripheral
self.writeTransferPeripheral?.characteristic = char

这样,以后使用变量写入值时,该变量仍为零。 似乎您应该像这样设置元组的值:

self.writeTransferPeripheral = (peripheral, char)