【问题标题】:Scanning BLE peripheral and connecting to it扫描 BLE 外围设备并连接到它
【发布时间】:2019-04-30 18:49:35
【问题描述】:

对于 BLE 和编码移动应用程序来说相当陌生。我尝试了几个演示并遇到了这个https://github.com/RickRedSix/BLE4.0-iOS-Swift-Demo 问题是它没有连接到我的 BLE 设备,所以我假设它只扫描当时的 BLE 设备创建者,所以我总是收到错误“只能在开机状态下接受此命令”。我需要更改代码中的任何部分以使其扫描另一个外围设备吗?我是否需要在某处指定设备的 UUID、MAC 地址或其他唯一信息?

感谢您对此问题的任何帮助

【问题讨论】:

    标签: swift xcode bluetooth bluetooth-lowenergy


    【解决方案1】:

    该消息意味着您应该打开蓝牙电源,然后搜索设备。类似的东西:

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .unknown:
            print("Unknown")
        case .resetting:
            print("Resetting")
        case .unsupported:
            print("Unsupported")
        case .unauthorized:
            print("Unauthorized")
        case .poweredOff:
            print("Powered Off")
            central.stopScan()
        case .poweredOn:
            print("Powered On")
            central.scanForPeripherals(withServices: nil, options: nil)
        }
    }
    

    【讨论】:

    • 尝试将这些案例添加到我的项目中,但我仍然遇到与以前相同的错误。我已尝试将扫描设置为所有可用的外围设备,但仍然无法正常工作。
    【解决方案2】:

    大约一年前,我开发了一个应用程序来扫描并连接到 BLE 设备。从该项目发布代码。如果您按原样复制粘贴它可能无法正常工作。但我 100% 确定这正是您想要实现的目标。

    我也使用了“https://github.com/RickRedSix/BLE4.0-iOS-Swift-Demo”作为参考。

    希望这可以帮助您解决问题。如果您有任何疑问,请告诉我。

    import UIKit
    import CoreLocation
    import CoreBluetooth
    
    class BLEDeviceTableViewController: UIViewController, CLLocationManagerDelegate, UITableViewDelegate, UITableViewDataSource, CBCentralManagerDelegate, CBPeripheralDelegate {
    
    private var myTableView: UITableView!
    
    var manager : CBCentralManager!
    var myBluetoothPeripheral = [CBPeripheral]()
    var myCharacteristic : CBCharacteristic!
    
    var isMyPeripheralConected = false
    
    var peripheralNames = [String]()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let displayWidth: CGFloat = self.view.frame.width
    
        manager = CBCentralManager(delegate: self, queue: nil)
    
        myTableView = UITableView(frame: CGRect(x: 0, y: 135, width: displayWidth, height: (self.view.frame.height-(self.view.frame.height/3))-10))
        myTableView.register(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
        myTableView.dataSource = self
        myTableView.delegate = self
        self.view.addSubview(myTableView)
    
        // Do any additional setup after loading the view.
    }
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
    
        var msg = ""
    
        switch central.state {
    
        case .poweredOff:
            msg = "Bluetooth is Off"
        case .poweredOn:
            msg = "Bluetooth is On"
            manager.scanForPeripherals(withServices: nil, options: nil)
        case .unsupported:
            msg = "Not Supported"
        default:
            msg = "?"
    
        }
    
        print("STATE: " + msg)
    
    }
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    
    
    
        peripheralNames.append(peripheral.name ?? "Unknown Device")
        print(peripheral)
    
    
        self.myBluetoothPeripheral.append(peripheral)      //save peripheral
    
        print(peripheralNames)
        myTableView.reloadData()
    }
    
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        print("Connected to \(peripheral.name ?? "Uknown Device")")
        availableDeviceLabel.text = "Connected to \(peripheral.name ?? "Uknown Device")"
        isMyPeripheralConected = true //when connected change to true
        peripheral.delegate = self
        peripheral.discoverServices(nil)
    }
    
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        isMyPeripheralConected = false //and to falso when disconnected
    }
    
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    
        print("Services:\(String(describing: peripheral.services)) and error\(String(describing: error))")
        if let services = peripheral.services {
            for service in services {
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
    
    }
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    
    
        print("peripheral:\(peripheral) and service:\(service)")
    
        for characteristic in service.characteristics!
        {
            peripheral.setNotifyValue(true, for: characteristic)
        }
    
    }
    
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    
        let readValue = characteristic.value
    
        print("Response from BLE Device: \(readValue)")
    
    }
    
    //if you want to send an string you can use this function.
    func writeValue() {
    
        if isMyPeripheralConected {
    
            //check if myPeripheral is connected to send data
    
            //let dataToSend: Data = "Hello World!".data(using: String.Encoding.utf8)!
    
            //myBluetoothPeripheral.writeValue(dataToSend, for: myCharacteristic, type: CBCharacteristicWriteType.withoutResponse)    //Writing the data to the peripheral
    
        } else {
            print("Not connected")
        }
    }
    
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    
        //let indexPath = NSIndexPath(forRow: tag, inSection: 0)
        //let cell = tableView.cellForRow(at: indexPath) as! gpsSettingsCustomCell!
        //print(cell?.cellLabel.text ?? "")
    
        self.myBluetoothPeripheral[indexPath.row].delegate = self
    
        manager.stopScan()                          //stop scanning for peripherals
        manager.connect(myBluetoothPeripheral[indexPath.row], options: nil)
    
        myTableView.deselectRow(at: indexPath, animated: true)
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 60
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return peripheralNames.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = gpsSettingsCustomCell(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 60), title: "Hello")
        cell.cellLabel.text = peripheralNames[indexPath.row]
        cell.cellLabel2.text = "Bluetooth Device"
        return cell
    
    }
    
    class BLEDeviceCustomCell: UITableViewCell {
    //var cellButton: UIButton!
    var cellLabel: UILabel!
    var cellLabel2: UILabel!
    
    init(frame: CGRect, title: String) {
        super.init(style: .default, reuseIdentifier: "cell")
        //super.init(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
    
        cellLabel = UILabel(frame: CGRect(x: 10, y: 10, width: self.frame.width, height: 20))
        cellLabel.font = UIFont(name: "Titillium-Regular", size: 14.0)
        //cellLabel= UILabel(frame: CGRectMake(self.frame.width - 100, 10, 100.0, 40))
        cellLabel.textColor = UIColor.black
        //cellLabel.font = //set font here
    
        cellLabel2 = UILabel(frame: CGRect(x: 10, y: 30, width: self.frame.width, height: 20))
        cellLabel2.font = UIFont(name: "Titillium-Regular", size: 14.0)
        cellLabel2.textColor = UIColor.gray
        //cellButton = UIButton(frame: CGRectMake(5, 5, 50, 30))
        //cellButton.setTitle(title, forState: UIControlState.Normal)
    
        addSubview(cellLabel)
        addSubview(cellLabel2)
        //addSubview(cellButton)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }
    

    【讨论】:

    • 非常感谢您的回复 Cedan。运行此程序时出现错误,可能是因为代码不能补充其余代码。这是您从 Rick 的代码中为 Cedan 项目更改的唯一部分吗?如果您在某处上传了 xcode 文件,那将不胜感激。
    • @Campbell 好的,给一个小时左右的时间,我将分享一个 Xcode 项目,该项目可以无错误地实现此代码。我刚刚从我的项目中复制了上面的代码,所以你说它不起作用,因为它没有与其余代码连接。所以我很快就会分享一个项目。
    • @Campbell 所以我为你创建了一个测试项目。您可以在此链接中找到它。 dropbox.com/s/0onurtjd723ynn2/BLE%20Test.zip?dl=0 确保您遵循这些步骤以使其正常工作。 1. 确保您在真实设备上运行此程序。 2. 应用程序要找到BLE设备,下载并安装LightBlue Explorer在另一台设备上并创建一个虚拟外设,以便运行代码的设备可以扫描并找到您创建的这个测试蓝牙外设。或者您也可以使用任何其他 BLE 设备,例如健身手环等。让我知道它是否有效。
    • 我理解这个想法,它真的很酷。我的问题是我希望应用程序连接到 BLE 模块,因此无法在其上下载 Lightblue explorer。非常感谢您的帮助,尽管这意义重大。
    • @Campbell 您使用的是哪种 BLE 模块?当你运行我发给你的项目时,它是否显示BLE模块的名称???