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
48 changes: 48 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.

95 changes: 94 additions & 1 deletion packages/carp_connectivity_package/lib/connectivity_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,48 @@ class BluetoothDevice {
', rssi: $rssi';
}

/// Beacon device data.
@JsonSerializable(includeIfNull: false, explicitToJson: true)
class BeaconDevice {
/// The RSSI signal strength to the device.
int rssi;

/// Beacon UUID (for iBeacon).
String? uuid;

/// Major value (for iBeacon).
int? major;

/// Minor value (for iBeacon).
int? minor;

double? accuracy;

BeaconDevice({
required this.rssi,
this.uuid,
this.major,
this.minor,
this.accuracy,
}) : super();

factory BeaconDevice.fromRangingResult(BeaconDevice result) => BeaconDevice(
uuid: result.uuid,
major: result.major,
minor: result.minor,
accuracy: result.accuracy,
rssi: result.rssi,
);

factory BeaconDevice.fromJson(Map<String, dynamic> json) => _$BeaconDeviceFromJson(json);
Map<String, dynamic> toJson() => _$BeaconDeviceToJson(this);

@override
String toString() => '$runtimeType - '
', uuid: $uuid, major: $major, minor: $minor, accuracy: $accuracy'
', rssi: $rssi';
}

/// A [Data] holding wifi connectivity status in terms of connected SSID
/// and BSSID.
///
Expand Down Expand Up @@ -216,9 +258,55 @@ class Wifi extends Data {
String toString() => '${super.toString()}, SSID: $ssid, BSSID: $bssid, IP: $ip';
}

/// A [Data] holding information of nearby Bluetooth devices.
@JsonSerializable(includeIfNull: false, explicitToJson: true)
class BeaconData extends Data {
static const dataType = ConnectivitySamplingPackage.BLUETOOTH;

/// Timestamp of scan start.
late DateTime startScan;

/// Timestamp of scan end, if available.
DateTime? endScan;

/// A map of [BeaconDevice] indexed by their [bluetoothDeviceId] to make
/// sure that the same device only appears once.
final Map<String, BeaconDevice> _scanResult = {};

/// The list of [BeaconDevice] found in a scan.
List<BeaconDevice> get scanResult => _scanResult.values.toList();
set scanResult(List<BeaconDevice> devices) => _scanResult.addEntries(
devices.map(
(device) => MapEntry(
device.uuid ?? '',
device,
),
),
);

BeaconData({DateTime? startScan, this.endScan}) : super() {
this.startScan = startScan ?? DateTime.now();
}

void addBluetoothDevice(BeaconDevice device) => _scanResult[device.uuid ?? ''] = device;

void addBluetoothDevicesFromRangingResults(BeaconDevice result) {
addBluetoothDevice(BeaconDevice.fromRangingResult(result));
}

@override
Function get fromJsonFunction => _$BeaconDataFromJson;
factory BeaconData.fromJson(Map<String, dynamic> json) => FromJsonFactory().fromJson<BeaconData>(json);
@override
Map<String, dynamic> toJson() => _$BeaconDataToJson(this);

@override
String toString() => '${super.toString()}, scanResult: $scanResult';
}

/// Beacon Region to use when monitoring for beacons.
@JsonSerializable(includeIfNull: false, explicitToJson: true)
class BeaconRegion {
class BeaconRegion extends Data {
/// A unique identifier for the beacon region.
/// Used to distinguish between different regions being monitored.
String identifier;
Expand Down Expand Up @@ -251,6 +339,11 @@ class BeaconRegion {
);
}

factory BeaconRegion.fromJson(Map<String, dynamic> json) => FromJsonFactory().fromJson<BeaconRegion>(json);

@override
Map<String, dynamic> toJson() => _$BeaconRegionToJson(this);

@override
String toString() => '${super.toString()}, Identifier: $identifier, UUID: $uuid, Major: $major, Minor: $minor';
}
55 changes: 43 additions & 12 deletions packages/carp_connectivity_package/lib/connectivity_package.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ class ConnectivitySamplingPackage extends SmartphoneSamplingPackage {
/// * Use a [IntervalSamplingConfiguration] for configuration.
static const String WIFI = "${NameSpace.CARP}.wifi";

/// Measure type for Beacon ranging to detect and estimate proximity to
/// Bluetooth beacons (e.g., iBeacon, Eddystone).
/// * Typically returns beacon identifiers (UUID, major, minor) and
/// estimated distance or RSSI.
/// * Use a [PeriodicSamplingConfiguration] for configuration.
static const String BEACON = "${NameSpace.CARP}.beacon";

@override
DataTypeSamplingSchemeMap get samplingSchemes => DataTypeSamplingSchemeMap.from([
DataTypeSamplingScheme(
Expand Down Expand Up @@ -49,6 +56,18 @@ class ConnectivitySamplingPackage extends SmartphoneSamplingPackage {
IntervalSamplingConfiguration(
interval: const Duration(minutes: 10),
)),
DataTypeSamplingScheme(
CamsDataTypeMetaData(
type: BEACON,
displayName: "Ranging beacons in proximity",
timeType: DataTimeType.POINT,
permissions: [Permission.bluetoothScan, Permission.locationAlways],
),
PeriodicSamplingConfiguration(
interval: const Duration(minutes: 10),
duration: const Duration(seconds: 10),
),
),
]);

@override
Expand All @@ -60,6 +79,8 @@ class ConnectivitySamplingPackage extends SmartphoneSamplingPackage {
return BluetoothProbe();
case WIFI:
return WifiProbe();
case BEACON:
return BeaconProbe();
default:
return null;
}
Expand Down Expand Up @@ -102,32 +123,42 @@ class BluetoothScanPeriodicSamplingConfiguration extends PeriodicSamplingConfigu
/// List of remote device IDs to filter the scan results.
List<String> withRemoteIds;

/// Use Package `flutter_beacon` to enable beacon monitoring while the app is in background.
bool useBeaconMonitoring;

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);
}

@JsonSerializable(includeIfNull: false, explicitToJson: true)
class BeaconRangingPeriodicSamplingConfiguration extends PeriodicSamplingConfiguration {
/// List of beacon regions to monitor and/or range using the `flutter_beacon` package.
///
/// When [useBeaconMonitoring] is true, the app will monitor these regions, potentially in the background if platform permissions and conditions allow.
List<BeaconRegion?> beaconRegions;

/// When a device is within this distance from the beacon, a predefined event is triggered.
/// Defaults to 2 meters.
int beaconDistance;

BluetoothScanPeriodicSamplingConfiguration({
BeaconRangingPeriodicSamplingConfiguration({
required super.interval,
required super.duration,
this.withServices = const [],
this.withRemoteIds = const [],
this.beaconRegions = const [],
this.useBeaconMonitoring = false,
this.beaconDistance = 2,
});

@override
Map<String, dynamic> toJson() => _$BluetoothScanPeriodicSamplingConfigurationToJson(this);
Map<String, dynamic> toJson() => _$BeaconRangingPeriodicSamplingConfigurationToJson(this);
@override
Function get fromJsonFunction => _$BluetoothScanPeriodicSamplingConfigurationFromJson;
factory BluetoothScanPeriodicSamplingConfiguration.fromJson(Map<String, dynamic> json) =>
FromJsonFactory().fromJson<BluetoothScanPeriodicSamplingConfiguration>(json);
Function get fromJsonFunction => _$BeaconRangingPeriodicSamplingConfigurationFromJson;
factory BeaconRangingPeriodicSamplingConfiguration.fromJson(Map<String, dynamic> json) =>
FromJsonFactory().fromJson<BeaconRangingPeriodicSamplingConfiguration>(json);
}
Loading