Подключение и запись на несколько периферийных устройств с одним CBManager - PullRequest
0 голосов
/ 20 сентября 2019

Я пытаюсь создать приложение для iOS, которое использует библиотеку CoreBluetooth для запуска / остановки и передачи данных из нескольких инерциальных единиц измерения, которые оснащены модулями HM-10 BLE 4.0.У меня нет проблем с подключением / записью / чтением только с одного модуля, но я не могу подключиться более чем к одному.Что мне нужно сделать, чтобы это сделать?

Я попытался создать несколько CBManager без удачи, и я только что попытался подключиться к нескольким периферийным устройствам, щелкнув одну строку в моей таблицес помощью

for peripheral in peripherals
{
CBManager.connect(myPeripheral)
}

Эти параметры не сработали, и я надеялся, что смогу получить некоторые рекомендации о том, что делать дальше.Я довольно новичок в Swift и только что поднял его за последние пару недель.

Вот то, что я имею, когда я ищу соединения Bluetooth:

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")
                }

            }

        }

    }


С текущим кодом I 'Я отправил сообщение об ошибке, которое возвращает

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?

Кто-нибудь может дать некоторые рекомендации по этому вопросу?Это высоко ценится.

1 Ответ

1 голос
/ 20 сентября 2019

Я думаю, что вижу проблему.После подключения к первому периферийному устройству вы извлекаете текущий контроллер вида из контроллера навигации.При этом массив периферийных устройств будет освобожден, поскольку контроллер больше не доступен.Следовательно, нет ссылки на текущие обнаруженные периферийные устройства.Когда нет ссылки на периферийное устройство, оно будет отключено.(Представьте, что закрытие приложения, подключенного к периферийному устройству, приведет к отключению).

Решение:

Вместо того, чтобы устанавливать parentView в качестве делегата периферийного устройства, установите self (ScanTableViewController) в качестве делегатаи не высовывайте контроллер.Другими словами, сделайте то, что сохранит ссылку.

...