CBCentralManager connecting to a CBPeripheralManager, connects then disconnects?

c, core-bluetooth, ios, objective-c

Solution

Here's your problem:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {

    NSLog(@"Discovered %@ at %@", peripheral.name, RSSI);
    if (_discoveredPeripheral != peripheral) {
        // Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it
        _discoveredPeripheral = peripheral;
        // And connect
        NSLog(@"Connecting to peripheral %@", peripheral);
        [_centralManager connectPeripheral:peripheral options:nil]; // <-- this is the issue

        // then stop scanning for peripherals
        [_centralManager stopScan];
        NSLog(@"Scanning stopped");
    }
}

You're connecting to a weakly held object, you should connect to your _discoveredPeripheral object instead. Also, don't forget to update your property calls to use your BCPeripheral object, for example:

[_discoveredPeripheral discoverServices:@[[CBUUID UUIDWithString:BLUNO_TRANSFER_SERVICE_UUID]]];

Problem

I have an iOS device (iPod Touch 5G) acting as a CBCentralManager, and Bluno acting as a CBPeripheralManager. When I attempt to connect to the peripheral with the central it appears to connect for a second or two then disconnects. I can see a LED on the Bluno light up for a second or two then dim down. I know there isn't a problem with the Bluno because I can use the LightBlue app on the iPod Touch to connect to the peripheral. So the problem probably lies somewhere in my code. As of right now, I am getting the following message when I status syslog, ``` CoreBluetooth[WARNING] <CBCentralManager: 0x16e77470> is disabling duplicate filtering, but is using the default queue (main thread) for delegate events ``` Not sure if that is related to the connect / disconnect problem. The code I have constructed is as follows, Services.h ``` #define BLUNO_TRANSFER_SERVICE_UUID @"0xDFB0" #define BLUNO_TRANSFER_CHARACTERISTIC_UUID @"0xDFB2" ``` ViewControllerDev2.h ``` #import <Foundation/Foundation.h> #import <CoreBluetooth/CoreBluetooth.h> #import <QuartzCore/QuartzCore.h> #import "SERVICES.h" @interface ViewControllerDev2 : UIViewController <CBCentralManagerDelegate, CBPeripheralDelegate, UITextViewDelegate> { } @property (weak, nonatomic) IBOutlet UIBarButtonItem *btnDone; // Core Bluetooth Peripheral stuff @property (strong, nonatomic) CBCentralManager *centralManager; @property (strong, nonatomic) CBPeripheral *discoveredPeripheral; @property (strong, nonatomic) NSMutableData *data; @property (strong, nonatomic) IBOutlet UITextView *textView; @property (weak, nonatomic) IBOutlet UIButton *btnSend; - (IBAction)dismissScene:(id)sender; - (IBAction)sendBTData:(id)sender; @end ``` ViewControllerDev2.m ``` #import "ViewControllerDev2.h" @implementation ViewControllerDev2 - (void)viewDidLoad { [super viewDidLoad]; _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil]; // options:nil is an iOS 7 feature _data = [[NSMutableData alloc] init]; } - (void)viewDidUnload { [self setBtnDone:nil]; [super viewDidUnload]; } - (IBAction)sendBTData:(id)sender { //[self sendData]; } - (IBAction)dismissScene:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; [_centralManager stopScan]; } - (void)centralManagerDidUpdateState:(CBCentralManager *)central { // You should test all scenarios if (central.state != CBCentralManagerStatePoweredOn) { return; } if (central.state == CBCentralManagerStatePoweredOn) { // Scan for devices [_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:BLUNO_TRANSFER_SERVICE_UUID]] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }]; NSLog(@"Scanning started"); } } - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { NSLog(@"Discovered %@ at %@", peripheral.name, RSSI); if (_discoveredPeripheral != peripheral) { // Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it _discoveredPeripheral = peripheral; // And connect NSLog(@"Connecting to peripheral %@", peripheral); [_centralManager connectPeripheral:peripheral options:nil]; // then stop scanning for peripherals [_centralManager stopScan]; NSLog(@"Scanning stopped"); } } - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"Failed to connect"); [self cleanup]; } - (void)cleanup { // See if we are subscribed to a characteristic on the peripheral if (_discoveredPeripheral.services != nil) { for (CBService *service in _discoveredPeripheral.services) { if (service.characteristics != nil) { for (CBCharacteristic *characteristic in service.characteristics) { if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:BLUNO_TRANSFER_CHARACTERISTIC_UUID]]) { if (characteristic.isNotifying) { [_discoveredPeripheral setNotifyValue:NO forCharacteristic:characteristic]; return; } } } } } } [_centralManager cancelPeripheralConnection:_discoveredPeripheral]; } - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { NSLog(@"Connected"); [_centralManager stopScan]; NSLog(@"Scanning stopped"); [_data setLength:0]; peripheral.delegate = self; [peripheral discoverServices:@[[CBUUID UUIDWithString:BLUNO_TRANSFER_SERVICE_UUID]]]; } - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { if (error) { [self cleanup]; return; } for (CBService *service in peripheral.services) { [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:BLUNO_TRANSFER_CHARACTERISTIC_UUID]] forService:service]; } // Discover other characteristics } - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { if (error) { [self cleanup]; return; } for (CBCharacteristic *characteristic in service.characteristics) { if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:BLUNO_TRANSFER_CHARACTERISTIC_UUID]]) { [peripheral setNotifyValue:YES forCharacteristic:characteristic]; } } } - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { if (error) { NSLog(@"Error"); return; } NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding]; // Have we got everything we need? if ([stringFromData isEqualToString:@"EOM"]) { //[_textview setText:[[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]]; [peripheral setNotifyValue:NO forCharacteristic:characteristic]; [_centralManager cancelPeripheralConnection:peripheral]; } [_data appendData:characteristic.value]; } - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:BLUNO_TRANSFER_CHARACTERISTIC_UUID]]) { return; } if (characteristic.isNotifying) { NSLog(@"Notification began on %@", characteristic); } else { // Notification has stopped [_centralManager cancelPeripheralConnection:peripheral]; } } - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { _discoveredPeripheral = nil; [_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:BLUNO_TRANSFER_SERVICE_UUID]] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }]; } @end ```

Original source