iOS CoreBluetooth : centralManager:didConnectPeripheral / didFailToConnectPeripheral: not getting called
Asked Answered
R

2

24

I'm pulling my hair out of this problems. I'm trying to connect to BLE devices, can't see what I've done wrong in my code below.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    _cm = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

+ (NSString*)UUIDString:(CFUUIDRef)uuid {
    CFStringRef string = CFUUIDCreateString(NULL, uuid);
    return (__bridge_transfer NSString*)string;
}

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    if (central.state == CBCentralManagerStatePoweredOn) {
        [self scanForPeripherals];
    }
}

- (void)centralManager:(CBCentralManager *)central
 didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary *)advertisementData
                  RSSI:(NSNumber *)RSSI {
//    NSLog(@"Received peripheral : \n%@", peripheral);
//    NSLog(@"Adv data : %@", advertisementData);

    [peripheral setDelegate:self];
    [central connectPeripheral:peripheral options:nil];
    [peripheral readRSSI];
}

- (int)scanForPeripherals {
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:NO], CBCentralManagerScanOptionAllowDuplicatesKey,
                             nil];

    [_cm scanForPeripheralsWithServices:nil options:options];
    return 0;
}

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@"didConnectPeripheral");
}

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"didDisconnectPeripheral");
}

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"failed to connect");
}

- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error {
    NSLog(@"didReadRSSI");
}

These devices are not my own. I don't know its proximity UUID, but as far as I know, It won't be needed in connecting via CoreBluetooth right?

All of the devices are discovered in didDiscoverPeripheral:, in the selector I tried to connect them. But there's nothing comes after that.

Am I to expect a dialog with Pairing Password Request when I called to didDiscoverPeripheral:? If so I don't see any dialog, why is that?

From apple documents, It clearly stated that after trying to connect to a device you should get a called to either didConnectPeripheral or didFailToConnectPeripher but I got none.

Any thoughts? I've been trying for almost a week now. Appreciate every helps, thanks.

Rena answered 15/10, 2014 at 8:4 Comment(5)
Do you get a call to didDiscoverPeripheral? Have you tried removing the call to [peripheral readRSSI] that immediately follows your connect request? You shouldn't issue that request until you are connected. I always suggest people try the free LightBlue app from the app store as a test to see if their device is advertising and is connectableCuttlebone
Yes I've tried, There was the first version of this code where, it's do nothing but, discover and try to connect, but after connectPeripheral executed nothing happen.Rena
Try LightBlue - this way you can at least confirm that the hardware is connectable. Also try storing the peripheral you are connecting to in a property so that it isn't releasedCuttlebone
Tried, All of them shows up in LightBlue, No services was displayed for any devices. There are 2 of The Estimotes BLE and another 2 of my country customized BLE*. Interrogating the estimotes BLE result in successful connection but after a fews seconds, LightBlue says "Disconnected alert", and There is a red text saying "Data is stale", for another 2 devices interrogation disclosing another page like the estimotes and nothing moreRena
May help: #28168304Statecraft
C
62

If you don't somehow retain the peripheral object that is delivered to didDiscoverPeripheral then it is released once this delegate method exits and you won't get a connection.

I suggest adding a property to track discovered peripherals

@property (strong,nonatomic) NSMutableArray *peripherals;

initialise this in viewDidLoad or init

self.peripherals=[NSMutableArray new];

And then add the peripheral to it in didDiscoverPeripheral

-(void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    NSLog(@"Discovered peripheral %@",peripheral.identifier.UUIDString);
    [self.peripherals addObject:peripheral];
    [central connectPeripheral:peripheral options:nil];
}
Cuttlebone answered 15/10, 2014 at 9:28 Comment(10)
Yes!!! That does the trick, Thank you so much @Paulw11. I didn't know that peripheral passed in from didDiscoverPeripheral was weak referenced. I also don't find anything telling about this in apple docs or it was me skipping that part? Anyway, thanks a bunch!!!.Rena
I don't know how I found it - I think I had to figure it out the hard way. Anyway I compared my app with your code and that was the differenceCuttlebone
Good catch. I also notified just now, after your answer, that all tutorial I've been working after keep reference to the connected devices. A small matter, but surely thanks a lot, again. @CuttleboneRena
@Cuttlebone My app doesn't get launched in the background when I turn the bluetooth off.. I have asked a question here: #48030980Helmsman
@Cuttlebone does the centralManagerDidUpdateState method gets called when user turns on the bluetooth after a couple of hours? I am stuck where centralManagerDidUpdateState doesn't get called if I turn the radio off and turn it on after a few hours.Helmsman
I don't believe that didUpdateState is called in the background; I would need to check.Cuttlebone
@Cuttlebone when I turn off the bluetooth while the app is connected, and I turn it on after few minutes nothing seems to be called in the app. And when I manually launch the app, peripheral is stuck in connecting state. How can I recover from this situation. I have asked a detail question here: #48030980Helmsman
@Cuttlebone I need to remain connected to the app at all times in the background. It works perfectly, until I turn the radio off while in connected state. On turning on it never notifies the app.Helmsman
@Cuttlebone Can you please have a look at this. #53322247Ibby
@paulw11 Can you tell me one thing When I go in background func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) method will called in my side and give me a state of service.How I scan new devices in background using center manger ?Can you give me idea?Termitarium
B
4
var peripherals = [CBPeripheral]()

func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
    peripherals.append(peripheral)
    bleManager.connectPeripheral(peripheral, options: nil)
}

This is the Swift version.

Burnett answered 5/1, 2016 at 11:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.