fix: smooth scan RSSI readings
This commit is contained in:
@ -45,6 +45,7 @@ class BluetoothController {
|
||||
BluetoothController(this._ble);
|
||||
|
||||
static const int defaultMtu = 64;
|
||||
static const Duration _rssiAverageWindow = Duration(milliseconds: 500);
|
||||
|
||||
final FlutterReactiveBle _ble;
|
||||
|
||||
@ -52,6 +53,7 @@ class BluetoothController {
|
||||
StreamSubscription<DiscoveredDevice>? _scanResultsSubscription;
|
||||
Timer? _scanTimeout;
|
||||
final Map<String, DiscoveredDevice> _scanResultsById = {};
|
||||
final RssiAverager _rssiAverager = RssiAverager(window: _rssiAverageWindow);
|
||||
final _scanResultsSubject =
|
||||
BehaviorSubject<List<DiscoveredDevice>>.seeded(const []);
|
||||
final _isScanningSubject = BehaviorSubject<bool>.seeded(false);
|
||||
@ -102,6 +104,7 @@ class BluetoothController {
|
||||
|
||||
_scanTimeout?.cancel();
|
||||
_scanResultsById.clear();
|
||||
_rssiAverager.clear();
|
||||
_scanResultsSubject.add(const []);
|
||||
_isScanningSubject.add(true);
|
||||
|
||||
@ -112,7 +115,12 @@ class BluetoothController {
|
||||
requireLocationServicesEnabled: requireLocationServicesEnabled,
|
||||
)
|
||||
.listen((device) {
|
||||
_scanResultsById[device.id] = device;
|
||||
final smoothedRssi = _rssiAverager.addSample(
|
||||
device.id,
|
||||
device.rssi,
|
||||
DateTime.now(),
|
||||
);
|
||||
_scanResultsById[device.id] = device.copyWith(rssi: smoothedRssi);
|
||||
_scanResultsSubject
|
||||
.add(_scanResultsById.values.toList(growable: false));
|
||||
}, onError: (Object error, StackTrace st) {
|
||||
@ -394,3 +402,26 @@ class BluetoothController {
|
||||
return Ok(null);
|
||||
}
|
||||
}
|
||||
|
||||
class RssiAverager {
|
||||
RssiAverager({required this.window});
|
||||
|
||||
final Duration window;
|
||||
final Map<String, List<(DateTime, int)>> _samplesByDeviceId = {};
|
||||
|
||||
int addSample(String deviceId, int rssi, DateTime timestamp) {
|
||||
final cutoff = timestamp.subtract(window);
|
||||
final samples = _samplesByDeviceId.putIfAbsent(deviceId, () => []);
|
||||
|
||||
samples
|
||||
..removeWhere((sample) => sample.$1.isBefore(cutoff))
|
||||
..add((timestamp, rssi));
|
||||
|
||||
final total = samples.fold<int>(0, (sum, sample) => sum + sample.$2);
|
||||
return (total / samples.length).round();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_samplesByDeviceId.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user