10

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?

Jonathan
  • 111
  • 1
  • 4

3 Answers3

8

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
Aboelseoud
  • 556
  • 1
  • 7
  • 22
  • 3
    Yes, but I need to continually get an updated RSSI. My findings are that once Central Manager has discovered and rediscovered a peripheral a few times, then it stops discovering it (seems to be around 3 seconds) even when the scan continues. What I'm left with is needing to re-initiate the scan repeatedly to try to get updated RSSI values. – Jonathan May 16 '13 at 18:53
  • 4
    Yeah, you can re-initiate the scan inside the didDiscoverPeripheral function, and by that you'll be getting the RSSI quickly forever. – Aboelseoud May 16 '13 at 20:14
  • 2
    Thanks. That works. In order to conserve power I actually stop scan after 100ms and then do a 100ms burst every second or so. Works great. – Jonathan May 20 '13 at 02:23
  • 1
    Can you please point to documentation where a peripheral can not connect to more than one central? In CBCentralManagerDelegate, there is a function called - (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals, where peripherals is an array. – Jon Oct 23 '13 at 23:21
  • Hi Jonathan, can you please post your snippets code to do that ? – megabri Feb 27 '15 at 07:23
5

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

2

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];
}
eskimwier
  • 1,037
  • 13
  • 16