使用一个 CBManager 连接和写入多个外围设备

Posted

技术标签:

【中文标题】使用一个 CBManager 连接和写入多个外围设备【英文标题】:Connecting and writing to multiple peripherals with one CBManager 【发布时间】:2019-09-20 04:48:53 【问题描述】:

我正在尝试制作一个 ios 应用程序,该应用程序使用 CoreBluetooth 库来启动/停止并传输来自配备 HM-10 BLE 4.0 模块的多个惯性测量单元的数据。我只从一个模块连接/写入/读取没有问题,但我无法获得与多个模块的连接。我需要做什么才能做到这一点?

我尝试创建多个 CBManager,但没有成功,我只是尝试通过单击表中的一行来连接多个外围设备,

for peripheral in peripherals

CBManager.connect(myPeripheral)

这些选项没有奏效,我希望我能获得一些关于下一步尝试的指导。我对 Swift 很陌生,在过去的几周里刚刚开始学习它。

这是我在搜索蓝牙连接时所需要的:

import UIKit
import CoreBluetooth

class ScanTableViewController: UITableViewController, CBCentralManagerDelegate 

    var peripherals:[CBPeripheral] = []
    var manager:CBCentralManager? = nil
    var parentView:MainViewController? = nil

    //This is my tableView where I try to connect to all the peripherals
    // that come back in the table by just selecting one peripheral. 
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        for peripheral in peripherals
            manager?.connect(peripheral, options: nil)
        
    

    // CBCentralManagerDelegate Methods

    // I think this is where I'm having issues, how do I pass all the connected peripherals on to the next view?
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) 

        //pass reference to connected peripheral to parent view
        parentView?.mainPeripheral = peripheral
        peripheral.delegate = parentView
        peripheral.discoverServices(nil)

        //set the manager's delegate view to parent so it can call relevant disconnect methods
        manager?.delegate = parentView
        parentView?.customiseNavigationBar()

        if let navController = self.navigationController 
            navController.popViewController(animated: true)
        

        print("Connected to " +  peripheral.name!)
    


这是我使用 Connection 的课程:

// MainViewController.swift
//Bo Heyse

import UIKit
import CoreBluetooth

class MainViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate 
    var manager:CBCentralManager? = nil
    var mainPeripheral:CBPeripheral? = nil
    var mainCharacteristic:CBCharacteristic? = nil

    let BLEService = "FFE0"
    let BLECharacteristic = "FFE1"

    @IBOutlet weak var recievedMessageText: UILabel!


    //how do I get this function to send a connection to all the peripherals?
    @IBAction func sendButtonPressed(_ sender: AnyObject) 
        let helloWorld = "Hello World!"
        let dataToSend = helloWorld.data(using: String.Encoding.utf8)

        if (mainPeripheral != nil) 
            mainPeripheral?.writeValue(dataToSend!, for: mainCharacteristic!, type: CBCharacteristicWriteType.withoutResponse)
         else 
            print("haven't discovered device yet")
        
    

    // MARK: - CBCentralManagerDelegate Methods    
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) 
        mainPeripheral = nil
        customiseNavigationBar()
        print("Disconnected" + peripheral.name!)
    


    // MARK: CBPeripheralDelegate Methods
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) 

        for service in peripheral.services! 

            print("Service found with UUID: " + service.uuid.uuidString)

            //device information service
            if (service.uuid.uuidString == "180A") 
                peripheral.discoverCharacteristics(nil, for: service)
            

            //GAP (Generic Access Profile) for Device Name
            // This replaces the deprecated CBUUIDGenericAccessProfileString
            if (service.uuid.uuidString == "1800") 
                peripheral.discoverCharacteristics(nil, for: service)
            

            //Bluno Service
            if (service.uuid.uuidString == BLEService) 
                peripheral.discoverCharacteristics(nil, for: service)
            

        
    

    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) 

        //get device name
        if (service.uuid.uuidString == "1800") 

            for characteristic in service.characteristics! 

                if (characteristic.uuid.uuidString == "2A00") 
                    peripheral.readValue(for: characteristic)
                    print("Found Device Name Characteristic")
                

            

        

        if (service.uuid.uuidString == "180A") 

            for characteristic in service.characteristics! 

                if (characteristic.uuid.uuidString == "2A29") 
                    peripheral.readValue(for: characteristic)
                    print("Found a Device Manufacturer Name Characteristic")
                 else if (characteristic.uuid.uuidString == "2A23") 
                    peripheral.readValue(for: characteristic)
                    print("Found System ID")
                

            

        

        if (service.uuid.uuidString == BLEService) 

            for characteristic in service.characteristics! 

                if (characteristic.uuid.uuidString == BLECharacteristic) 
                    //we'll save the reference, we need it to write data
                    mainCharacteristic = characteristic

                    //Set Notify is useful to read incoming data async
                    peripheral.setNotifyValue(true, for: characteristic)
                    print("Found Bluno Data Characteristic")
                

            

        

    


使用我发布的当前代码,我得到一个返回的错误

API MISUSE: Forcing disconnection of unused peripheral <CBPeripheral: 0x280ab4000, 
identifier = B5835D05-CE72-D9EC-1526-2967566810F1, name = HEAD, 
state = connected>. Did you forget to cancel the connection?

有人可以就这个问题提供一些指导吗?非常感谢。

【问题讨论】:

欢迎来到 ***。您在获得此问题的有用答案方面的变化很小。代码太多,与不相关的 UI 代码混合在一起,您提供了两种变体(循环连接,在 UITableView 委托中连接)并混合描述等。请改进您的问题。创建一个最小的可重现示例。 When a row is selected, you connect to all peripherals, not just the one in that row, Is that intentional? 【参考方案1】:

我想我可以看到问题所在。连接到第一个外围设备后,从导航控制器中弹出当前视图控制器。通过这样做,您的外围设备阵列将被释放,因为控制器不再可用。因此,没有参考当前发现的外围设备。当没有对外围设备的引用时,它将断开连接。 (想想关闭连接到外围设备的应用程序会强制断开连接)。

解决方案:

不要将 parentView 设置为外围代理,而是将 self (ScanTableViewController) 设置为代理并且不要弹出 Controller。换句话说,做一些可以保留参考的事情。

【讨论】:

以上是关于使用一个 CBManager 连接和写入多个外围设备的主要内容,如果未能解决你的问题,请参考以下文章

使用 Ionic Native BLE 向 BLE 外围设备发出写入值

如何通过android应用连接多个BLE设备?

Android-BlutoothBle,蓝牙中心设备(peripheral)向外围设备(GattServer)连续写入多个Characteristic的注意事项

如何解决 [CoreBluetooth] 警告:对于具有多个设备连接的外围设备来说,这不是一个有效的特征

CoreBluetooth:检索多个断开连接的外围设备的正确方法是啥?

外围设备未连接到 iOS