I am looking for a way to connect to only the nearest peripheral based on the RSSI. My goal is to leave other peripherals listed but only have the closest peripheral connect.

Since RSSI is only available while the device is connected, would it make sense to wait till all the devices are connected then determine the closest peripheral based on the RSSI then disconnect the rest?

Connect

- (void) connectToPeripheral:(CBPeripheral *)peripheral
{
    NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE],CBConnectPeripheralOptionNotifyOnDisconnectionKey,nil];
    [myCBCentralManager connectPeripheral:peripheral options:options];
}

Delegates used

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

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error;

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;

CBPeripheral

/*!
 *  @property RSSI
 *
 *  @discussion While connected, the RSSI of the link in decibels.
 */
@property(retain, readonly) NSNumber *RSSI;
有帮助吗?

解决方案

This is what worked best for me. I initially scanned for Peripherals and then just selected the one with the highest RSSI. (Yes, this DOES report back the RSSI for every device. You do NOT need to be connected to it first).

However, I found this to be unreliable. There were just too much fluctuations in the RSSI value. So I did the following instead.

I used:

NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];//allow duplicates with YES
[self.CM scanForPeripheralsWithServices:uuidArray options:options]; 

The callback is:

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

This will continue to report the RSSI of every peripheral until you call the method:

[self.CM stopScan];

The "didDiscoverPeripheral" you will be called for every ad packet that the Central (your iPhone) sees. Add a routine in this callback to average the RSSI for each unique peripheral found. My experience was that a 1 second scan time was sufficient, but it depends on how often your peripheral is advertising (i.e. its advertising interval)

其他提示

You can read the rssi value of each peripheral in the didDiscoverPeripheral Delegate Method without beeing connected.

Use https://github.com/LGBluetooth/LGBluetooth/ It scans peripherals and sorts by average RSSI.

[[LGCentralManager sharedInstance] scanForPeripheralsByInterval:4
                                                     completion:^(NSArray *peripherals)
 {
 }];

Here is sample code which will scan peripherals for 4 sec and sort them by RSSI

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top