Refreshing RSSI value of many bluetooth peripheral

2019-06-06 17:00发布

问题:

I'm trying to mesure RSSI indicator on iOS (6 with BLE) from several bluetooth peripheral. I can get RSSI with scanForPeripheral :

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

[_manager scanForPeripheralsWithServices:nil
                                 options:options];

coupled with:

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

this works but I have no control on the rate of packets receive and the result seems uncertain.

I've read : https://stackoverflow.com/a/12486927/270209 but my rate is not close to 100ms at all (more 1~2 seconds)

If I'm connected to the device the result with readRSSI seems more reliable.

I'm looking for a way to "stimulate" peripherals for more frequents updates in scan mode or a way to connect to more than one peripheral at a time.

Thanks

Edit : I've also tried to start / stop scan quickly, it seems that at start scan detects more devices and updates are more frequent

回答1:

I'm sure you've already figured this out but just in case someone comes across this (like I just did) looking for other info, if you're not using other iOS devices with coreLocation you need to call the peripheralDidUpdateRSSI: delegate using [self.myPeripheral readRSSI];.

You can call for RSSI data updates in didUpdateValueForCharacteristic: as often as you like once in the updateValue delegate.

You don't need this in viewDidLoad: NSDictionary *options = etc... This NSDictionary is created in the didDiscoverPeripheral: delegate.

So the overall flow would be:

Check that you are receiving RSSI in the NSLog where you obtained the RSSI data...

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

NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];

 if ([localName length] > 0){
    NSLog(@"Discovered: %@ RSSI: %@", peripheral.name, RSSI);
    // your other needs ...
}

Call peripheralDidUpdateRSSI: here since this is where updates will occur continuously if you've set notify value to YES [peripheral setNotifyValue:YES forCharacteristic:characteristic];

- (void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{

//Call the peripheralDidUpdateRSSI delegate ..
[self.myPeripheral readRSSI];

// do all of your other characteristic value updates here 
}

readRSSI will call the delegate where you perform your RSSI updates on your UILabel (or whatever you're using) every time you update the previous characteristics values:

- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error;
{
_rssiLabel.text = [self.myPeripheral.RSSI stringValue];
NSLog(@"RSSI Method”);   
}

If you don't need characteristic values for your app just run a loop in there with whatever timing you need the RSSI value to refresh.



回答2:

(Assuming you're on an iOS device:) CoreBluetooth is likely deliberately limiting the rate at which it's active on the antenna. Bluetooth LE, Bluetooth Classic, and Wi-Fi are all on the same antenna on iOS devices, so the radios try to keep unnecessary chatter to a minimum. You could try filing a bug on CoreBluetooth to add an option or way to control the update frequency, but I don't imagine they'll implement it, as their primary design goals are to: 1. Not drain the device's battery unnecessarily and 2. Co-exist with the other antenna's radios. (They've also said in posts on the Apple devforums that, for example, if you want a higher data rate than the iOS BTLE implementation, you should use Bluetooth Classic or something that's been designed for it. BTLE is meant to be low-power first and foremost, and they've taken that to its logical end.)



回答3:

Indeed, the delay between peripheral.readRSSI() and peripheralDidUpdateRSSI is like a second!

I think the best way is to read the RSSI value on the BLE device itself and send it to the iOS device.



回答4:

The peripheral advertises based on the firmware of the peripheral. This can be set from as low at 100ms to almost as high as 2 seconds. When using an iOS device as a Bluetooth Peripheral, I have found no way of changing it. Here is Apples documentation: Look in section 3.5... https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf