首页 > 解决方案 > 使用一个 CBManager 连接和写入多个外围设备

问题描述

我正在尝试制作一个 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!)
    }
}

这是我使用连接的类:

// 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?

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

标签: iosswiftbluetooth-lowenergycore-bluetooth

解决方案


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

解决方案:

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


推荐阅读