Joakim
Joakim

Reputation: 3294

Scanning for Peripherals offering specific services, But doesn't find Services on discovered peripheral

I'm experimenting with the CoreBluetooth Framework for iOS and I'm facing an issue that I find very Strange.

Once I have a Connected Peripheral, I want to discover it's services - but it fails. Despite searching for and finding Peripherals which offer a specific service. See the code below:

func centralManagerDidUpdateState(central: CBCentralManager) {
    if(central.state != .PoweredOn) {
        print("Returning due to wrong state: ", central.state)
        return;
    }
    print("Starting peripheral scan")
    manager.scanForPeripheralsWithServices(serviceUUID, options: nil)
}

Peripheral Scanning is started and looking for specified serviceUUIDs. In this case: serviceUUIDs = [CBUUID(string: "13333333-3333-3333-3333-333333333337")]. If I change the String, No service is discovered at all (as expected).

func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
    print("Discovered peripheral: ", peripheral.name)
    if(peripheral.name == "PizzaSquat") {
        print("Advertising data: ", advertisementData)
        print("RSSI: ", RSSI)
        activePeripheral = peripheral
        print("Connecting to peripheral")
        manager.connectPeripheral(peripheral, options: nil)
    }
}

On a Linux computer, I have a Bleno instance running which is displaying as a Peripheral with the name "PizzaSquat" (And obviously offers a Service, since it's discovered at all. So when this Peripheral is discovered, I connect to it.

func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {
    print("Connected to Peripheral: ", peripheral.name)
    if(peripheral.services == nil) {
        print("Starting service discovery")
        peripheral.delegate = self
        peripheral.discoverServices(serviceUUIDs)
    } else {
        print("Already has services: ")
        for service: CBService in peripheral.services! {
            print(service)
        }
    }
}

Once connected (to "PizzaSquat"), I check if it already has services (It doesn't) and start Service discovery. Everything is correct up to this point - But no Services are ever discovered. I expect the below function to be called:

func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
    print("Discovered new Service")
    for service: CBService in peripheral.services! {
        print(service)
    }
}

with at least one service, Since the Peripheral shouldn't be discovered at all if it didn't have the specified Service!

I have also tried to call peripheral.discoverServices(nil) to discovery any Service, but still no response.

Could someone help me find the problem?

Upvotes: 1

Views: 2583

Answers (1)

Shay Thompson
Shay Thompson

Reputation: 81

When you scan for CBPeripheral objects, the peripheral service UUID is obtained from the advertisement packet. The peripheral is basically saying, "Oh yeah, I have this service UUID!" iOS picks that up and passes the CBPeripheral to you.

But the peripheral might not be synced with what is in the advertisement packet. It's a non-binding agreement that the advertisement packet matches what's actually in the peripheral's service/characteristic hierarchy.

So what this means is that it's possible for a peripheral to advertise one service UUID, but actually contain another (or none).

Check out LightBlue on iOS or nRF Control Panel on Android to see if the service/characteristic hierarchy matches what you think it does. In LightBlue you should be able to view the advertisement data and compare it to the services on the peripheral you're connected to.

Upvotes: 4

Related Questions