Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS CoreBluetooth: startAdvertising() Error advertising static data

I want to advertise static data. I'm using Swift 2.2.1 and CoreBluetooth on iOS. My app builds bluetooth Services and their corresponding Characteristics, then calls startAdvertising(), and the peripheralManagerDidStartAdvertising90 callback returns this error:

peripheralManagerDidStartAdvertising encountered an error. // Mine
One or more parameters were invalid. // ...from Apple CoreBluetooth
nil  // ... return value from Apple CoreBluetooth callback

I'm relatively new to Swift and iOS development so my guess is that I'm doing something goofy, but so far I can't figure out what.

I'll attempt to distill things down for more experienced eyes.

- - - - - - pointutility.swift - - - - - - -
// This is a code excerpt and probably won't compile.

// UUID for the one peripheral service, declared outside the class:
var peripheralServiceUUID = CBUUID(string: "9BC1F0DC-F4CB-4159-BD38-7375CD0DD545")

// UUID for one characteristic of the service above, declared outside the class:
var nameCharacteristicUUID = CBUUID(string: "9BC1F0DC-F4CB-4159-BD38-7B74CD0CD546")

class PointUtility: NSObject, CBPeripheralManagerDelegate {

var peripheralManager:CBPeripheralManager?
var bluetoothServices:CBMutableService?
var nameCharacteristic:CBMutableCharacteristic?

override init() {
    super.init()
    peripheralManager = CBPeripheralManager(delegate:self, queue:nil)
    bluetoothServices = CBMutableService(type: peripheralServiceUUID, primary: true)
}

func configureUtilityForIdentity(identity:Point!) {
    var characteristicsArray:[CBCharacteristic] = []
    myIdentity = identity

      if (identity.name != nil) {
        nameCharacteristic =
            CBMutableCharacteristic(type: nameCharacteristicUUID,
                properties: (CBCharacteristicProperties.Read),
                value: myIdentity?.name?.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false),
                permissions: CBAttributePermissions.Readable)

        characteristicsArray.append(nameCharacteristic!)
      }

    // more characteristics built here and added to the characteristicsArray[]...
    // ... then all are added to the CBMutableService at the bottom...
    bluetoothServices?.characteristics = characteristicsArray as [CBCharacteristic]
}


func peripheralManagerDidUpdateState(peripheral: CBPeripheralManager) {
    switch (peripheral.state) {
    case .PoweredOn:
        print("Current Bluetooth State:  PoweredOn")
        publishServices(bluetoothServices)
        break;
    case .PoweredOff:
        print("Current Bluetooth State:  PoweredOff")
        break;
    case .Resetting:
        print("Current Bluetooth State:  Resetting")
        break;
    case .Unauthorized:
        print("Current Bluetooth State:  Unauthorized")
    case .Unknown:
        print("Current Bluetooth State:  Unknown")
        break;
    case .Unsupported:
        /
        print("Current Bluetooth State:  Unsupported")
        break;
    }
}

func publishServices(newService:CBMutableService!) {
    peripheralManager?.addService(newService)
}

func peripheralManager(peripheral: CBPeripheralManager, didAddService service: CBService, error: NSError?) {

    if (error != nil) {
        print("PerformerUtility.publishServices() returned error: \(error!.localizedDescription)")
        print("Providing the reason for failure: \(error!.localizedFailureReason)")
    }
    else {
        peripheralManager?.startAdvertising([CBAdvertisementDataServiceUUIDsKey : service.UUID])
    }
}

func peripheralManagerDidStartAdvertising(peripheral: CBPeripheralManager,
    error: NSError?) {
        if (error != nil) {
            print("peripheralManagerDidStartAdvertising encountered an error.")
            print(error!.localizedDescription)  // Error: One or more parameters were invalid
            print(error!.localizedFailureReason)  // Error: nil
        }
        print ("Debug: peripheralManagerDidStartAdvertising()")
}
}
- - - - - - pointutility.swift - - - - - - -

I really appreciate any assistance offered.

Best Regards,

Michael

like image 785
Cascadia_Mike Avatar asked Mar 08 '16 03:03

Cascadia_Mike


2 Answers

The value for the CBAdvertisementDataServiceUUIDsKey in the dictionary passed to startAdvertising is an array of CBUUID objects, but you are only passing a single CBUUID. Once I changed it to an array your code worked.

func peripheralManager(peripheral: CBPeripheralManager, didAddService service: CBService, error: NSError?) {

    if (error != nil) {
        print("PerformerUtility.publishServices() returned error: \(error!.localizedDescription)")
        print("Providing the reason for failure: \(error!.localizedFailureReason)")
    }
    else {
        peripheralManager?.startAdvertising([CBAdvertisementDataServiceUUIDsKey : [service.UUID]])
    }
}
like image 113
Paulw11 Avatar answered Nov 04 '22 19:11

Paulw11


The error parameter in the method:

func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?)

Reports the error:

Error Domain=CBErrorDomain Code=1 "One or more parameters were invalid." UserInfo={NSLocalizedDescription=One or more parameters were invalid.}

Issue was needing to pass an array of UUIDs and also use the CBUUID(string:) type rather than UUID(uuidString:). Each issue reproduces the error independently.

struct BluetoothPeripheral {
    let localName: String
    let uuid: String

    func peripheralData() -> [String : Any] {
        return [
            CBAdvertisementDataLocalNameKey    : localName,
            CBAdvertisementDataServiceUUIDsKey : [CBUUID(string: uuid)],
        ]
    }
}
like image 36
pkamb Avatar answered Nov 04 '22 20:11

pkamb