0

Until now the iPhone has paired to a bluetooth device when the app is opened, but I want to pair with a button click instead. I tried to put all the scanning and connection functions in a IBAction, but nothing happens when I push the button. In the first function after the IBAction I have a print output to check if it even enters the function, but I don't get the print. I also tried to put a delay after the manager.scanForPeripherals but didn't work either. What am I missing here? anyone know? Thanks for any replies! here is my code (without the delay):

var manager: CBCentralManager!
var device: CBPeripheral?
var characteristics: [CBCharacteristic]?
var serviceUUID = "1234"
var char1 = "FFE1"
let deviceName = "HMSoft"
var connected = CBPeripheralState.connected
var disconnected = CBPeripheralState.disconnected

 override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    manager = CBCentralManager(delegate: self, queue: nil)


}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


}
 func centralManagerDidUpdateState(_ central: CBCentralManager) {
    switch central.state {
    case .poweredOn: break
        // manager.scanForPeripherals(withServices: nil, options: nil)
    case .unknown: break

    case .resetting: break

    case .unsupported: break

    case .unauthorized: break

    case .poweredOff:

        break

    }
}


   @IBAction func connectBluetooth(_ sender: Any) {

   manager.scanForPeripherals(withServices: nil, options: nil)

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {

    if let peripheralName = advertisementData[CBAdvertisementDataLocalNameKey] as? String {

        if peripheralName == self.deviceName {

            // save a reference to the sensor tag
            self.device = peripheral
            self.device!.delegate = self

            // Request a connection to the peripheral

            self.manager.connect(self.device!, options: nil)

            print("Check")
        }
    }
}

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {

    peripheral.discoverServices(nil)
}


func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {

    if error != nil {

        return
    }


    if let services = peripheral.services {
        for service in services {

            if (service.uuid == CBUUID(string: serviceUUID)) {
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
    }

}


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

    device = peripheral
    characteristics = service.characteristics

}

func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
    if error != nil {

        return
    }
}

}

hoddy
  • 127
  • 3
  • 10

2 Answers2

0

Don't put the function func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) inside the button.

Try instead this:

@IBAction func connectBluetooth(_ sender: Any) {
   manager = CBCentralManager(delegate: self, queue: nil)
   manager.scanForPeripherals(withServices: nil, options: nil)
}

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {

    if let peripheralName = advertisementData[CBAdvertisementDataLocalNameKey] as? String {

        if peripheralName == self.deviceName {

            // save a reference to the sensor tag
            self.device = peripheral
            self.device!.delegate = self

            // Request a connection to the peripheral

            self.manager.connect(self.device!, options: nil)

            print("Check")
        }
    }
}

It's quite important that the device know that BLE is on before you can scan.

func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch (central.state) {
        case .unsupported:
            print("BLE is unsupported")
        case .unauthorized:
            print("BLE is unauthorized")
        case .unknown:
            print("BLE is unknown")
        case .resetting:
            print("BLE is reseting")
        case .poweredOff:
            print("BLE is powered off")
        case .poweredOn:
            print("BLE is powered on")
            //must be called
        }
    }
kuzdu
  • 7,124
  • 1
  • 51
  • 69
  • Thank you! what you said + moving manager.scanForPeripherals(withServices: nil, options: nil) to case .poweredOn worked :D – hoddy Feb 27 '18 at 18:16
  • Say if I am wrong but when you move it to .poweredOn it will be called automatically? – kuzdu Feb 27 '18 at 19:04
  • it will be called automatically after I hit the button (calling manager = CBCentralManager(delegate: self, queue: nil). if I then turn off bluetooth, and on again, scanning is called automatically again. Hope this answered your question :) – hoddy Feb 28 '18 at 10:12
  • Then I misunderstood you. I thought you only want scan when you hit the button. But now you scan automatically when you switch BLE from off to on. Anyway you mark this as solved so everything is fine – kuzdu Feb 28 '18 at 10:37
0

When you initialise the CBCentralManager and set its delegate, the delegate will start receiving events.

So, if you only want the CBCentralManager to be active once the user has tapped a button, rather than as soon as the screen loads, the minimum you have to do is move the code that initialises the manager from viewDidLoad to the button action.

So:

Move manager = CBCentralManager(delegate: self, queue: nil) from viewDidLoad to @IBAction func connectBluetooth(_ sender: Any),

Remove the call to scanForPeripherals from the IBAction, and;

Uncomment // manager.scanForPeripherals(withServices: nil, options: nil) in centralManagerDidUpdateState.

Cezar
  • 55,636
  • 19
  • 86
  • 87
  • Thank you so much :D this worked like a charm! Guess I have to do some reading on delegates. Still learning basics :) – hoddy Feb 27 '18 at 18:15