angryip
angryip

Reputation: 2290

Swift: CBCentralManager cannot find any devices

I am attempting to follow the tutorial on this page, towards listing and communicating with BLE devices.

Unlike the author, I am not interested in making a GUI application, and would rather keep it console based.

I have made two files to test bluetooth communication, main.swift and BluetoothWorker.swift.

The main class looks as follows:

import Foundation

var worker = BluetoothWorker();
worker.findStretchSensor();

while worker.foundAddresses.isEmpty {
    print("### no devices found, sleeping");
    sleep(5);
    print("### done sleeping");
}

Here is how my Bluetooth class looks like:

import Foundation

import CoreBluetooth;

class BluetoothWorker: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {

    var foundAddresses = [String]();
    var manager = CBCentralManager();
    var myPherif: CBPeripheral?;

    func findStretchSensor() {
        manager = CBCentralManager(delegate: self, queue: nil);

        print("### we are in the find sensor");
        if (myPherif != nil) {
            print("### we are canceling");
            manager.cancelPeripheralConnection(myPherif!);
        }

        print("### we are scanning for devices");
        manager.scanForPeripherals(withServices: nil, options: nil);
    }


    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        print("### we are checking the state");
        if (central.state != CBCentralManagerState.poweredOn) {
            print("### bluetooth is not available");
        }
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        print("we found a device");
        if (peripheral.name != nil) {
            let message: String = "found peripheral:: " + peripheral.name!;
            foundAddresses.append(peripheral.name!);
            print(message);
        }
    }
}

My console output looks as follows:

### we are in the find sensor
### we are scanning for devices
### no devices found, sleeping
### done sleeping
### no devices found, sleeping
### done sleeping
### no devices found, sleeping

I cannot for the life of me figure out why any of the devices are not listed, ad why the delegated methods are not executing. If I download this example library ( that works very similar to one of my bluetooth devices ), my device is recognized. ( Note, this library is also GUI based )

Is there something obvious I am missing?

Upvotes: 1

Views: 1907

Answers (1)

Lars Blumberg
Lars Blumberg

Reputation: 21441

Two things I'm seeing here:

  1. You're calling worker.findStretchSensor() too early.

You have to wait until centralManagerDidUpdateState() reports central.state == CBCentralManagerState.poweredOn, i.e:

func centralManagerDidUpdateState(_ central: CBCentralManager) {
    print("### we are checking the state");
    if (central.state == .poweredOn) {
        findStretchSensor()
    }
}

You're wrongly assuming that central.state is already powered when you create a CBCentralManager. That's not the case. It takes a while to receive the .poweredOn state.

  1. Since you're running an application without GUI, the main queue might not be adequate for handling the Bluetooth events, i.e. there might be no event loop where the Bluetooth stack could dispatch the events to. Probably that's why you're not getting any call to centralManagerDidUpdateState().

Have you tried creating passing a queue for the central manager? I.e.:

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

Upvotes: 2

Related Questions