This post is regarding an error I am getting from the Bluetooth API BlueJay. I have this error that I was not able to find documentation.
"CBCentralManager initialized."
"Bluejay with UUID: 6A7273D6-66D7-4C36-B6A4-E59DC84422F7 started."
2021-07-19 13:24:33.079775-0400 Argon18 UAT[9780:4330125] [connection] nw_endpoint_handler_set_adaptive_read_handler [C1.1 172.217.13.170:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for read_timeout failed
2021-07-19 13:24:33.080006-0400 Argon18 UAT[9780:4330125] [connection] nw_endpoint_handler_set_adaptive_write_handler [C1.1 172.217.13.170:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for write_timeout failed
"Error: unexpectedPeripheral(Bluejay.PeripheralIdentifier(uuid: 0BC9C8FE-74FB-A237-D61B-F28748FE7EC5, name: \"ARGON04280CEC\"))"
"Central manager state updated: Powered On"
I get this after the app starts the first thing it does on showing the main view is to try and connect to the default BLE device.
To do this I fetch from DB the entity for it and then using the store peripheral ID and peripheral name I create a PeripheralIdentifier struct and then past to the BluJay API.
this fails as per the error above, because of this I set up a button to manually retry this code and this does work.
I have the feeling that BlueJay is taking a long time to finish setting up and that I am sending the request too quickly after starting up BueJay.
this is the code to setup BluJay
self.bluejay.register(logObserver: self)
bluejay.registerDisconnectHandler(handler: self)
bluejay.register(connectionObserver: self)
bluejay.register(serviceObserver: self)
self.bluejay.start()
This code is set in a Singleton object this is called just before calling the connection. (I did test to call the initialiser at app start but I am getting the same problem)
This is the code called to get the BLE device info that is stored in the DB.
.onAppear(perform: {
let bleManager = A18BLEManager.shared
if bleManager.model == nil {
if let bike = A18DataStore.shared.getDefautBike(){
bleManager.connect(bikeID: bike.bleID!, name: bike.peripheralName!)
}
}
})
func getDefautBike() -> Bike?
{
var bike: Bike? //Bike is a NSManagedObject
let fetchRequest = Bike.fetchRequest() as NSFetchRequest<Bike>
if let idString = UserDefaults.standard.object(forKey: "defaultBikeUUID") as? String, let bleID = NSUUID(uuidString: idString)
{
fetchRequest.predicate = NSPredicate(format:"%K == %@", #keyPath(Bike.bleID), bleID)
}
do{
bike = try viewContext.fetch(fetchRequest).first
}
catch let error {
debugPrint("Fetch Error: \(error)")
}
return bike //does return a valid record with valid UUID and name
}
func connect(bikeID id: UUID, name: String) {
self.connect(PeripheralIdentifier(uuid: id, name: name))
}
func connect(_ peripheral: PeripheralIdentifier) {
self.bluejay.connect(peripheral, timeout: .seconds(15)) { [unowned self] connectionResult in
switch connectionResult {
case .success:
readBikeInfo()
debugPrint("Connection attempt to: \(peripheral.description) is successful")
case .failure(let error):
debugPrint("Error: \(error)")
}
}
}
the function getDefautBike() does return an object and the and the info is valide.
To test this I have a button setup in a different location in the app that calls this.
A18BLEManager.shared.connect(bikeID: UUID(uuidString: "0BC9C8FE-74FB-A237-D61B-F28748FE7EC5")!, name: "ARGON04280CEC")
And this call will work, it works only in the other view, if I use this on the main call site in the main view this will get the same error.
EDIT: Ok so after writing this. I tried to have the call set 5 seconds after the main view is presented. And indeed the connections works. So in the end the real question is how long does BlueJay takes to set up ?