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:
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:
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
Then:
But taking that object and calling
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.
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;
}
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>
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];
Code:
2012-08-17 12:00:58.255: didRetrieveConnectedPeripherals: (
"<CBConcretePeripheral: 0x106006970>"
)
Code:
[peripheral isConnected];
EDIT: This thread got moved to iOS, although this application is desktop specific.