IOBluetooth within Qt

Joined
Aug 17, 2012
Messages
1
Reaction score
0
Points
1
In a multiplatform application which uses Bluetooth Low Energy I am trying to utilize IOBluetooth.framework. I can scan for peripherals, but the problem is that I can't establish the connection with it. I have native obj-c applications for OSX and iOS and they work always without issues.
The whole attempt is here:
Code:
#define OBJC_CENTRAL_MANAGER   \
    ((CBCentralManager *) (ble->getCentralManager()))
#define OBJC_CENTRAL_MANAGER_DELEGATE    \
    ((id<CBCentralManagerDelegate>) (ble->getCentralManagerDelegate()))
#define OBJC_PERIPHERAL_DELEGATE \
    ((id<CBPeripheralDelegate>) (ble->getPeripheralDelegate()))

@interface ManagerDelegate : NSObject <CBCentralManagerDelegate>
{
@public
    BLEMac *ble;
    CBPeripheral *p;
}
@end

@implementation ManagerDelegate
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    if (!ble->checkBLECompatibility())
    {
        // XXX: no BLE device or hardware got turned off
        NSLog(@"No BLE or is off");
    }
}

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    NSLog(@"New fob! Name: %@ | Peripheral: %@ | RSSI: %ld", peripheral.name, peripheral, [RSSI integerValue]);
    CBCentralManager *manager = OBJC_CENTRAL_MANAGER;
    [manager connectPeripheral:peripheral options:nil];
}

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@"Connected to %@", [peripheral name]);
}

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

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

#undef OBJC_CENTRAL_MANAGER
#undef OBJC_CENTRAL_MANAGER_DELEGATE
#undef OBJC_PERIPHERAL_DELEGATE


class BLEMac::Private
{
public:
    // Obj-C instances
    CBCentralManager *manager;
    ManagerDelegate *managerDelegate;
    PeripheralDelegate *peripheralDelegate;
};

BLEMac::BLEMac()
{
    this->objc = new Private;
    this->objc->managerDelegate = [[ManagerDelegate alloc] init];
    this->objc->managerDelegate->ble = this;
    this->objc->peripheralDelegate = [[PeripheralDelegate alloc] init];
    this->objc->peripheralDelegate->ble = this;
    this->objc->manager = [[CBCentralManager alloc] initWithDelegate:this->objc->managerDelegate queue:nil];
}

bool BLEMac::init()
{
    if (this->checkBLECompatibility())
    {
        emit this->initDone(true);
        return true;
    }
    return false;
}

bool BLEMac::scan()
{
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE],
                                                                       CBCentralManagerScanOptionAllowDuplicatesKey,
                                                                       nil];
    [this->objc->manager scanForPeripheralsWithServices:nil options:options];
    return true;
}

bool BLEMac::checkBLECompatibility()
{
    NSLog(@"State: %d", this->objc->manager.state);
    switch ([this->objc->manager state]) {
        case CBCentralManagerStateUnsupported:
            NSLog(@"BLE is not supported.");
            return NO;
        case CBCentralManagerStateUnauthorized:
            NSLog(@"You do not have required permissions.");
            return NO;
        case CBCentralManagerStatePoweredOff:
            NSLog(@"BLE device is off");
            return NO;
        case CBCentralManagerStateUnknown:
            NSLog(@"BLE device is in unknown state");
            return YES; // XXX:
        case CBCentralManagerStatePoweredOn:
            NSLog(@"BLE powered ON");
            return YES;
        default:
            NSLog(@"BLE default case");
            return NO;
    }
}

void *BLEMac::getCentralManager()
{
    return (void *) this->objc->manager;
}

void *BLEMac::getCentralManagerDelegate()
{
    return (void *) this->objc->managerDelegate;
}

void *BLEMac::getPeripheralDelegate()
{
    return (void *) this->objc->peripheralDelegate;
}
On application startup BLEMac object is created and kept throughout the lifetime of the application to for managing BLE devices.
And this is the output I have:
Code:
2012-08-17 11:57:40.408: BLE device is in unknown state
2012-08-17 11:57:40.719: BLE powered ON
2012-08-17 11:57:40.817: New fob! Name: demo | Peripheral: <CBConcretePeripheral: 0x101555190> | RSSI: -68
2012-08-17 11:57:40.817: Connecting <CBConcretePeripheral: 0x101555190>
What I noticed is different in the native obj-c application is that on startup the BLE device is already ON, while in here it is in Unknown state and switches to ON before the first peripheral is printed out. So I assume that app loader executes some sort of pre-use code which prepares the hardware.
Another ackward thing is that if I launch a second client without shuting down the first one and try to call
Code:
[this->objc->manager retrieveConnectedPeripherals];
Then:
Code:
2012-08-17 12:00:58.255: didRetrieveConnectedPeripherals: (
    "<CBConcretePeripheral: 0x106006970>"
)
But taking that object and calling
Code:
[peripheral isConnected];
gives me NO, which means on establishing connection Apple API get stuck somewhere inside without completing the things it suppose to.

EDIT: This thread got moved to iOS, although this application is desktop specific.
 

Shop Amazon


Shop for your Apple, Mac, iPhone and other computer products on Amazon.
We are a participant in the Amazon Services LLC Associates Program, an affiliate program designed to provide a means for us to earn fees by linking to Amazon and affiliated sites.
Top