5

I'm trying to discover services from a BLE device I've connected to from my iOS app, but when my didDiscoverServices function gets called, the peripheral services array is empty.

The app connects to the device, runs peripheral.discoverServices(nil) and then the didDiscoverServices function gets called, but there are no services returned.

I've read a number of bluetooth related answers and other examples online and as best I can tell, my code is no different to what it should be, except it is not working. I feel like I must've missed something somewhere but I'm not sure what.

I've added my console log below for what I get when running the code, and the bluetooth code at the bottom for reference.

Bluetooth initialised
BLE is powered on
Optional("Nordic_Blinky") found at -72
Scanning stopped
Connect request sent
Connected to <CBPeripheral: 0x1c0301a70, identifier = 0887CF7F-98C8-3FCF-2D10-873FFFFB2B65, name = Nordic_Blinky, state = connected>
Discovering services
Services -- Optional([]) and Error -- nil

My BluetoothHandler class code is below

class BluetoothHandler : NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {

// MARK: Properties
var manager: CBCentralManager!
var targetPeripheral: CBPeripheral!


// MARK: Shared Instance
static let sharedInstance = BluetoothHandler()
private override init() {
    super.init()
    self.startManager()
    print("Bluetooth initialised")
}

// MARK: Functions

func startManager() {
    manager = CBCentralManager(delegate: self, queue: nil)
}

func centralManagerDidUpdateState(_ central: CBCentralManager) {

    var consoleMessage = ""
    switch (central.state) {

    case.poweredOn:
        consoleMessage = "BLE is powered on"
        manager.scanForPeripherals(withServices: nil, options: nil)

    case.poweredOff:
        consoleMessage = "BLE is powered off"

    case.resetting:
        consoleMessage = "BLE Resetting"

    case.unknown:
        consoleMessage = "BLE state unknown"

    case.unsupported:
        consoleMessage = "Device not supported by BLE"

    case.unauthorized:
        consoleMessage = "BLE not authorised"
    }
    print("\(consoleMessage)")

}

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

    if (peripheral.name == "Nordic_Blinky") {

        print("\(String(describing: peripheral.name)) found at \(RSSI)")
        self.stopScan()

        if targetPeripheral != peripheral {

            targetPeripheral = peripheral
            targetPeripheral!.delegate = self

            manager.connect(targetPeripheral, options: nil)
            print("Connect request sent")
        }

    }

    else if (peripheral.name != nil) {
        print("\(String(describing: peripheral.name))")
    }
}

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
    print("Connected to \(peripheral)")
    peripheral.delegate = self
    peripheral.discoverServices(nil)
    print("Discovering services")
}

func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Any) {
    print("Connection failed", error)
}

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

    if self.targetPeripheral != nil {
        self.targetPeripheral!.delegate = nil
        self.targetPeripheral = nil
    }
    print("Connection disconnected")
    self.startManager()
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    print("Services -- \(peripheral.services) and Error -- \(error)")

    if let services = peripheral.services {
        for service in services {
            peripheral.discoverCharacteristics(nil, for: service)
        }
    }
}
AdamDWalker
  • 271
  • 3
  • 8
  • Does an app like BlueLight.app found services? – Larme Sep 22 '17 at 13:51
  • @Larme yes an Android app did connect and get all the services from the device – AdamDWalker Sep 22 '17 at 13:59
  • `BlueLight.app` on iOS too? – Larme Sep 22 '17 at 14:25
  • @Larme it doesn’t show services for the iOS version, but I’m not sure if it may have cached anything, so I won’t be able to test this with a ‘clean’ iOS device until tomorrow or possibly Monday – AdamDWalker Sep 22 '17 at 16:33
  • If the LightBlue app on iOS doesn't show any services then the problem is with the peripheral. There is no caching involved. – Paulw11 Sep 22 '17 at 21:11
  • @AdamDWalker Have you solved the issue? I have similar situation. Android discovers services & characteristics but iOS doesn't (replicable in nrf Connect / light blue etc on many iOS devices) – zioolek Mar 18 '19 at 22:18
  • Yes the issue was resolved. It turned out to not be an iOS issue but rather the fault of the BLE device connection parameters being changed. iOS is much more strict with what it will and wont accept as connection parameters from the device, whereas Android doesn't really seem to care. Check out the Bluetooth accessories documentation for iOS, which has some suggested ranges that fixed things for us. – AdamDWalker Mar 28 '19 at 16:11

1 Answers1

0

Try this: swift 3

If your peripheral(BLE device) have services then print in log.

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

    if let services = peripheral.services as [CBService]!{

        for service in services{

            peripheral.discoverCharacteristics(nil, for: service)
        }
    }
    print("==>",peripheral.services!)
}

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

    for newChar: CBCharacteristic in service.characteristics!{

        print(newChar)
    }
}
Deepak Tagadiya
  • 2,187
  • 15
  • 28
  • 1
    I am already attempting to print the services to log, however it only prints an empty array as there are no services (see code and console log) – AdamDWalker Sep 23 '17 at 15:18