Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions carp_mobile_sensing/lib/domain.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions packages/carp_connectivity_package/lib/connectivity.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions packages/carp_connectivity_package/lib/connectivity_package.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,41 @@ class ConnectivitySamplingPackage extends SmartphoneSamplingPackage {
.add(WIFI, wifiNameAnonymizer);
}
}

/// A sampling configuration specifying how to scan for Bluetooth devices on a
/// regular basis for a specific period.
///
/// Data collection will be started as specified by the [interval] for a time
/// period specified as the [duration]. Bluetooth scanning is filtering
/// on the [withServices] and [withRemoteIds] to only collect data from
/// specific services and remote ids.
///
/// Filtering on remoteIds allows Android to scan for devices in the background
/// without needing to be in the foreground. This is not possible on iOS.
@JsonSerializable(includeIfNull: false, explicitToJson: true)
class BluetoothScanPeriodicSamplingConfiguration
extends PeriodicSamplingConfiguration {
/// List of Bluetooth service UUIDs to filter the scan results.
List<String> withServices;

/// List of remote device IDs to filter the scan results.
List<String> withRemoteIds;

BluetoothScanPeriodicSamplingConfiguration({
required super.interval,
required super.duration,
this.withServices = const [],
this.withRemoteIds = const [],
});

@override
Map<String, dynamic> toJson() =>
_$BluetoothScanPeriodicSamplingConfigurationToJson(this);
@override
Function get fromJsonFunction =>
_$BluetoothScanPeriodicSamplingConfigurationFromJson;
factory BluetoothScanPeriodicSamplingConfiguration.fromJson(
Map<String, dynamic> json) =>
FromJsonFactory()
.fromJson<BluetoothScanPeriodicSamplingConfiguration>(json);
}
25 changes: 24 additions & 1 deletion packages/carp_connectivity_package/lib/connectivity_probes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ class WifiProbe extends IntervalProbe {

/// The [BluetoothProbe] scans for nearby and visible Bluetooth devices and
/// collects a [Bluetooth] measurement that lists each device found during the scan.
///
/// Uses a [PeriodicSamplingConfiguration] for configuration the [interval]
/// and [duration] of the scan.
/// and [duration] of the scan. Can also be configured to filter by
/// [services] and [remoteIds] by using a [BluetoothScanPeriodicSamplingConfiguration].
class BluetoothProbe extends BufferingPeriodicStreamProbe {
/// Default timeout for bluetooth scan - 4 secs
static const DEFAULT_TIMEOUT = 4 * 1000;
Expand All @@ -70,11 +72,32 @@ class BluetoothProbe extends BufferingPeriodicStreamProbe {
Future<Measurement?> getMeasurement() async =>
_data != null ? Measurement.fromData(_data!) : null;

// if a BT-specific sampling configuration is used, we need to
// extract the services and remoteIds from it so FlutterBluePlus can
// perform filtered scanning

List<Guid> get services => (samplingConfiguration
is BluetoothScanPeriodicSamplingConfiguration)
? (samplingConfiguration as BluetoothScanPeriodicSamplingConfiguration)
.withServices
.map((e) => Guid(e))
.toList()
: [];

List<String> get remoteIds => (samplingConfiguration
is BluetoothScanPeriodicSamplingConfiguration)
? (samplingConfiguration as BluetoothScanPeriodicSamplingConfiguration)
.withRemoteIds
: [];

@override
void onSamplingStart() {
_data = Bluetooth();

try {
FlutterBluePlus.startScan(
withServices: services,
withRemoteIds: remoteIds,
timeout: samplingConfiguration?.duration ??
const Duration(milliseconds: DEFAULT_TIMEOUT));
} catch (error) {
Expand Down