CBCentralManager didFailToConnectPeripheral - ios

I'm developing an app for OS X (10.10) and iOS 8 to exchange some messages with a BLE peripheral. I want my app to find and connect to the peripheral, to send the message to it, and lastly to disconnect, so that the peripheral is free to be accessed from some other device. Everything works fine except for the following particular but still important situation: I scan for BLE devices and I find my device but still I don't connect to it because I have no messages to send. Then I walk away (out of range) or simply I turn the peripheral off. I still have saved in a var my CBPeripheral and I try to connect to it. Nothing happens while I would like the method centralManager:didFailToConnectPeripheral:error: to be called so that I can start to scan again.
centralManager:didConnectPeripheral working properly.
The documentation tells that bluetooth connection requests don't time out so I was wondering what other kinds of problems could lead to a connection failure
func connect(){
if let peripheral = self.peripheralBLE { //Check if the CBPeripheral I was looking for is properly stored
centralManager!.connectPeripheral(peripheral, options: nil)
}
else {
println("Nothing to connect"); //Didn't find any peripheral
}
}
func centralManager(central: CBCentralManager!, didConnectPeripheral peripheral: CBPeripheral!) {
print("connected");
println(peripheral.name);
if (peripheral == nil) {
return;
}
// Create new service class
if (peripheral == self.peripheralBLE) { //if it is the peripheral I was looking for then initialize the service for communication
self.bleService = RFduino(initWithPeripheral: peripheral)
}
connectionStatus = .connected; //update connection status
// Stop scanning for new devices
central.stopScan()
}
func centralManager(central: CBCentralManager!, didFailToConnectPeripheral peripheral: CBPeripheral!, error: NSError!) {
println("Failed to connect peripheral");
if peripheral == self.peripheralBLE{
self.bleService = nil;
self.peripheralBLE = nil;
self.connectionStatus = .disconnected;
}
self.startScanning();
}

Related

BLE Always getting "state = connecting" from CBPeripheral device

I am getting stuck to make the connection between device and iPhone always I got this state even I keep the reference of Peripheral at the file level OR global. :(
CBPeripheral: 0x1700f7200, identifier =
6F44C292-FA88-41B2-9534-F9EFFDC02708, name = (null), state =
connecting
I have to transfer data to the device also send some command.
I used the below code in didDiscover peripheral:
if (peripheral.identifier.uuidString == "6F44C292-FA88-41B2-9534-F9EFFDC02708") {//6F44C292-FA88-41B2-9534-F9EFFDC02708
connectingPeripheral = peripheral
connectingPeripheral.delegate = self
cbManager.connect(connectingPeripheral, options: [CBConnectPeripheralOptionNotifyOnDisconnectionKey:true])
cbManager.stopScan()
}
OR is there any way to check BLE device is working or not?

Cannot Subscribe to Notify Characteristic in iOS CoreBluetooth

I have successfully connected to BLE devices using the same code, but this device is not letting me subscribe. It's frustrating because I cannot figure out how to get a meaningful error message.
There is a Read/Notify/Indicate characteristic that I am attempting to listen to. The code I send is:
peripheral.setNotifyValue(true, for: characteristic)
my listener is:
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
if ((error) != nil) {
NSLog("Error changing notification state: " + error!.localizedDescription)
}
if characteristic.isNotifying {
NSLog("Notification Updated")
}
}
The error I get is:
Error changing notification state: Unknown ATT error.
I have downloaded another app that interfaces with this device successfully, so I know that the hardware is functioning properly.
I don't know if there is some sort of encryption or other setting that needs to be sent to allow communication with this device. Any advice would be appreciated.

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?
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.

How to get the characteristic(s) of HM-10 Bluetooth LE in iOS

I am trying to send some data from an iOS device to the HM-10 Bluetooth LE Module connected to an arduino. Problem is after connecting to the module discoverServices doesn't return a characteristic for the service.
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
if(error != nil) {
print(error?.description)
}
for service in peripheral.services! {
let thisService = service as CBService
print("Service: \(thisService.description)")
print("Characteristic: \(thisService.characteristics)")
}
}
This outputs:
Service: <CBService: 0x137e84ea0, isPrimary = YES, UUID = FFE0>
Characteristic: nil
I am a beginner with this arduino stuff as well as iOS. So any suggestions would be welcome. Maybe there is a way to write to the bluetooth module without knowing the characteristic... I have no idea.
I finally managed to get the answer. Because of my rudimentary understanding of the CoreBluetooth Framework I forgot to call discoverCharacteristics in didDiscoverServices. Well, I am really learning by doing. (I somehow thought discoverServices would call discoverCharacteristics itself.)

Bluetooth BLE Device disconnects as soon as connected?

I've been writing an app using Swift that connects to a bluetooth BLE device. For some reason, the app doesn't always connect to the device. In this case it will connect but gets disconnected straight away. This only happens maybe 1 in 10 times it connects, but definitely interferes with the reliability of the app.
I'm using CoreBluetooth to connect to the BLE device. Attempting connection again usually always gets it to reconnect, and other apps that communicate with this device works correctly every time, so I'm confident that it is not a problem with the peripheral.
I'd just like to know if there is anyone out there who has had a similar issue or if there is a particular reason why this may be happening?
EDIT: Here's the code for the willSelectRow of my table. This is where I get the peripheral to connect.
func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
centralManager.stopScan()
connectingPeripheral.append(discoveredDeviceArrayInfo[indexPath.row])
connectPeripheralNow(connectingPeripheral[0])
return indexPath
}
This is where I get it to connect, at this point I select the row which sets the CBPeripheral details of the device to connect to.
connectPeripheralNow looks like this:
func connectPeripheralNow(peripheral: CBPeripheral!){
self.centralManager.connectPeripheral(peripheral, options: nil)
}
didConnectPeripheral and didDiscoverServices looks like this
func centralManager(central: CBCentralManager,didConnectPeripheral peripheral: CBPeripheral)
{
peripheral.delegate = self
peripheral.discoverServices([CBUUID(string: "FFE5")])
print("SUCCESS: Connected to " + peripheral.name!)
}
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?)
{
if let servicePeripherals = peripheral.services as [CBService]!
{
for servicePeripheral in servicePeripherals
{
print("INFORMATION: Service discovered " + String(stringInterpolationSegment: servicePeripheral.UUID))
peripheral.discoverCharacteristics(nil, forService: servicePeripheral)
}
}
}
Just for the info, I do get a 'SUCCESS: Connected to xxx' message appear which shows that it is connecting. If you need more code, let me know!
What you are mentioning is more of an expected behaviour. BTLE is designed to consume very little amount of energy so it drops the connection as soon as possible. If you do not need a permanent connection then follow Discover --> Connect --> Read/write --> Setup timer --> When timer fires Connect.
If you need a permanent connection, you should subscribe for characteristic which transmits real time data like heart rate application. You would need to implement setNotifyValue:forCharacteristic: method. Read Apple Documentation for more details.

Resources