Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Bluetooth - constant RSSI updates of in-range devices

I just started with the core bluetooth framework for iOS and I'm developing an app that needs to constantly scan for BLE devices so that I can retrieve their RSSI number every minute or so.

Currently I have:

manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
[manager scanForPeripheralsWithServices:nil options:options];

this starts my app scanning for BLE devices and calls this delegate method when a device is discovered:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    NSLog(@"Did discover peripheral. peripheral: %@ rssi: %@, UUID: %@ advertisementData: %@ ", peripheral, RSSI, peripheral.UUID, advertisementData);
    //Do something when a peripheral is discovered.

    rssiLabel.text = [RSSI stringValue];

    [manager retrievePeripherals:[NSArray arrayWithObject:(id)peripheral.UUID]];}

this method gets me the peripheral's RSSI number which i can display. The last line then calls this delegate method:

- (void) centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals {

    NSLog(@"Currently known peripherals :");
    int i = 0;
    for(CBPeripheral *peripheral in peripherals) {
        NSLog(@"[%d] - peripheral : %@ with UUID : %@",i,peripheral,peripheral.UUID);

    }

     NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
     [manager scanForPeripheralsWithServices:nil options:options];

}

This code seems to be working and doing a scan roughly every 1 minute, but I don't exactly know why it working...

The documentation on core bluetooth is pretty sparse so if anyone has any idea on how to do this, or has a better way to do what I'm trying to accomplish I'd appreciate the help!

like image 636
kj13ennett Avatar asked Mar 28 '12 15:03

kj13ennett


2 Answers

Have you tried changing the scan option to YES?

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber  numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
[manager scanForPeripheralsWithServices:nil options:options];

If you do this you will get your "didDiscoverPeripheral" callback with every ad packet that is seen by your iPhone, which would normally be about every 100ms (although I see this callback timing varying a lot for the same device). This includes the RSSI of each device it sees.

This should be a lot faster than your ~1 minute update rate.

like image 124
Anders Avatar answered Sep 24 '22 04:09

Anders


Is far as I can see, this should do what you want.

When you started scanning for peripherals with the original call, your delegate should begin to get calls whenever a BLE device is discovered. This will continue until you stop the scan with a call to

[manager stopScan];

I don't think you actually need the second call to scanForPeripheralsWithServices in your centralManager:didRetrievePeripherals method, since, as far as I know, the scanning doesn't stop until you tell it to. I'm still getting started on this, too, though, and there may be a timeout I have not found, yet.

I'm pretty sure the reason you get a call about once a minute is because the BLE device is only advertising that often. If it advertises more often, like a device in discovery mode, I think you will get the calls more often. I would be interesting if you could confirm that. If the device has a discovery mode, you might try triggering it to see if the notices speed up.

like image 25
Mike Avatar answered Sep 25 '22 04:09

Mike