Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continuous scanning for iOS CoreBluetooth Central Manager?

The Low Energy Bluetooth spec does not say much about whether peripherals can connect to more than one central at a time, but my experience testing tells me that they cannot.

Because my application requires a non-possessive relationship with peripherals (i.e. no connections, which would block others), and needs to constantly update their RSSI values, I am seeking a way to continuously scan for peripherals and capture their RSSI values.

The scanForPeripheralsWithServices method appears to scan for a certain interval and then stops. I believe my best bet is to scan for 3 seconds at a time, stopScan, wait (several seconds) and then reinitiate a scan. Repeat.

Can anyone point to a better way of doing it? For example, configuring a peripheral to connect to more than one Central?

like image 476
Jonathan Avatar asked May 16 '13 01:05

Jonathan


3 Answers

I solved this type of issue with this code, basically just restarting the scanning every time an advertisement is processed. I was facing the same issue where CBCentralManager instance would stop listening to a peripheral.

(Setting CBCentralManagerScanOptionAllowDuplicatesKey to @YES did not fully solve the issue for me.)

Assuming the class implements CBCentralManagerDelegate:

- (id) init {
    self.central = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
    [self initScan];
}

- (void) initScan {
    [self.central stopScan];
    [self.central scanForPeripheralsWithServices:nil
                                         options:[NSDictionary dictionaryWithObjectsAndKeys:@NO, CBCentralManagerScanOptionAllowDuplicatesKey, nil]];
}

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

    //
    // Do stuff here
    //

    [self initScan];
}
like image 162
eskimwier Avatar answered Oct 30 '22 03:10

eskimwier


A peripheral cannot connect to more than one central. But if you need to just capture the RSSI then you don't even need connecting. Scanning for devices can retrieve the RSSI using this function:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
like image 8
Aboelseoud Avatar answered Oct 30 '22 05:10

Aboelseoud


As for the previous answer, if you are interested only in RSSI you can simply get it into the delegate method:

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

BTW, by default the CBCentralManager will only call this method once. If you need this callback to be called every time the CBCentralManager receives an advertisement packet you need to initiate the scan with the option CBCentralManagerScanOptionAllowDuplicatesKey set to YES:

NSDictionary *scanningOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey: @YES};
[centralManager scanForPeripheralsWithServices:nil options:scanningOptions];

Beware that Apple discourage the usage of this option if not strictly necessary.

See: iOS Developer Library -Best Practices for Interacting with a Remote Peripheral Device

like image 5
Dario Fiumicello Avatar answered Oct 30 '22 05:10

Dario Fiumicello