ipatch
ipatch

Reputation: 4053

CBCentralManager connecting to a CBPeripheralManager, connects then disconnects?

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

Upvotes: 2

Views: 8214

Answers (1)

Jason McDermott
Jason McDermott

Reputation: 411

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]]];

Upvotes: 7

Related Questions