Skip to content

Commit

Permalink
Improvement to SmartphoneDeploymentController based on issue #141 in …
Browse files Browse the repository at this point in the history
…the carp_study_app
  • Loading branch information
bardram committed Apr 19, 2023
1 parent b2b57d2 commit c294101
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 36 deletions.
29 changes: 13 additions & 16 deletions carp_core/lib/client/study_runtime.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,15 @@ class StudyRuntime<TRegistration extends DeviceRegistration> {
final List<DeviceConfiguration> _remainingDevicesToRegister = [];
Study? _study;
TRegistration? _deviceRegistration;
StudyStatus _status = StudyStatus.DeploymentNotStarted;
final StreamController<StudyStatus> _statusEventsController =
StreamController();

/// The unique device registration for this device.
/// Set in the [addStudy] method.
TRegistration? get deviceRegistration => _deviceRegistration;

/// The study for this study runtime.
/// Set in the [addStudy] method.
/// The study for this study runtime. Set in the [addStudy] method.
/// `null` if no study has been added yet.
Study? get study => _study;

/// The study deployment id for the [study] of this controller.
Expand All @@ -49,22 +48,20 @@ class StudyRuntime<TRegistration extends DeviceRegistration> {
Stream<StudyStatus> get statusEvents => _statusEventsController.stream;

/// The status of the [study] running on this [StudyRuntime].
StudyStatus? get status => _study?.status;
set status(StudyStatus? newStatus) {
if (newStatus != null) {
_study?.status = newStatus;
_statusEventsController.add(newStatus);
}
StudyStatus get status => _study?.status ?? StudyStatus.DeploymentNotStarted;
set status(StudyStatus newStatus) {
_study?.status = newStatus;
_statusEventsController.add(newStatus);
}

/// Has this [StudyRuntime] been initialized?
bool get isInitialized => (study != null);

/// Has the device deployment been completed successfully?
bool get isDeployed => (_status == StudyStatus.Deployed);
bool get isDeployed => (status == StudyStatus.Deployed);

/// Has the study and data collection been stopped?
bool get isStopped => (_status == StudyStatus.Stopped);
bool get isStopped => (status == StudyStatus.Stopped);

/// The list of devices that still remain to be registered before all devices
/// in this study runtime is registered.
Expand All @@ -89,7 +86,7 @@ class StudyRuntime<TRegistration extends DeviceRegistration> {
TRegistration deviceRegistration,
) async {
_study = study;
_status = StudyStatus.DeploymentNotStarted;
study.status = StudyStatus.DeploymentNotStarted;
_deviceRegistration = deviceRegistration;
}

Expand Down Expand Up @@ -126,10 +123,10 @@ class StudyRuntime<TRegistration extends DeviceRegistration> {
"Call 'configure()' first.");

// early out if already deployed.
if (status!.index >= StudyStatus.Deployed.index) return status!;
if (status.index >= StudyStatus.Deployed.index) return status;

// check the status of this deployment.
if (await getStudyDeploymentStatus() == null) return status!;
if (await getStudyDeploymentStatus() == null) return status;

status = StudyStatus.Deploying;

Expand Down Expand Up @@ -229,7 +226,7 @@ class StudyRuntime<TRegistration extends DeviceRegistration> {

/// Start collecting data for this [StudyRuntime].
@mustCallSuper
void start() => _status = StudyStatus.Running;
void start() => status = StudyStatus.Running;

/// Called when this [StudyRuntime] is disposed.
/// This entails stopping and disposing all data sampling and storage.
Expand All @@ -242,5 +239,5 @@ class StudyRuntime<TRegistration extends DeviceRegistration> {

/// Stop collecting data for this [StudyRuntime].
@mustCallSuper
Future<void> stop() async => _status = StudyStatus.Stopped;
Future<void> stop() async => status = StudyStatus.Stopped;
}
40 changes: 20 additions & 20 deletions carp_mobile_sensing/lib/runtime/deployment_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class SmartphoneDeploymentController extends StudyRuntime<DeviceRegistration> {
int _samplingSize = 0;
DataManager? _dataManager;
DataEndPoint? _dataEndPoint;
SmartphoneDeploymentExecutor? _executor;
final SmartphoneDeploymentExecutor _executor = SmartphoneDeploymentExecutor();
String _privacySchemaName = NameSpace.CARP;
late DataTransformer _transformer;

Expand All @@ -24,7 +24,7 @@ class SmartphoneDeploymentController extends StudyRuntime<DeviceRegistration> {
super.deviceRegistry as DeviceController;

/// The executor executing the [deployment].
SmartphoneDeploymentExecutor? get executor => _executor;
SmartphoneDeploymentExecutor get executor => _executor;

/// The configuration of the data endpoint, i.e. how data is saved or uploaded.
DataEndPoint? get dataEndPoint => _dataEndPoint;
Expand All @@ -47,7 +47,7 @@ class SmartphoneDeploymentController extends StudyRuntime<DeviceRegistration> {
///
/// This is a broadcast stream and supports multiple subscribers.
Stream<Measurement> get measurements =>
_executor!.measurements.map((measurement) => measurement
_executor.measurements.map((measurement) => measurement
..data = _transformer(TransformerSchemaRegistry()
.lookup(deployment?.dataEndPoint?.dataFormat ?? NameSpace.CARP)!
.transform(TransformerSchemaRegistry()
Expand All @@ -58,10 +58,10 @@ class SmartphoneDeploymentController extends StudyRuntime<DeviceRegistration> {
Stream<Measurement> measurementsByType(String type) => measurements
.where((measurement) => measurement.data.format.toString() == type);

// PowerAwarenessState powerAwarenessState = NormalSamplingState.instance;

/// The sampling size of this [deployment] in terms of number of [Measurement]
/// that has been collected.
/// that has been collected since sampling was started.
/// Note that this number is not persistent, and the counter hence resets
/// across app restart.
int get samplingSize => _samplingSize;

/// Create a new [SmartphoneDeploymentController] to control the runtime behavior
Expand Down Expand Up @@ -90,19 +90,21 @@ class SmartphoneDeploymentController extends StudyRuntime<DeviceRegistration> {
if (success) {
await AppTaskController().restoreQueue();
status = StudyStatus.Deployed;
return status!;
return status;
}
}

// if no cache, get the deployment from the deployment service
// and save a local cache
status = await super.tryDeployment();
if (status == StudyStatus.Deployed) deployment!.deployed = DateTime.now();
// if no user is specified for this study, look up the local user id
deployment!.userId ??= await Settings().userId;
await saveDeployment();
if (status == StudyStatus.Deployed && deployment != null) {
deployment!.deployed = DateTime.now();
// if no user is specified for this study, look up the local user id
deployment!.userId ??= await Settings().userId;
await saveDeployment();
}

return status!;
return status;
}

/// Save the [deployment] persistently to a cache.
Expand Down Expand Up @@ -174,8 +176,6 @@ class SmartphoneDeploymentController extends StudyRuntime<DeviceRegistration> {
// try to register relevant connected devices
super.tryRegisterRemainingDevicesToRegister();

_executor = SmartphoneDeploymentExecutor();

// initialize optional parameters
_dataEndPoint = dataEndPoint ?? deployment!.dataEndPoint;
_privacySchemaName = privacySchemaName;
Expand All @@ -200,14 +200,14 @@ class SmartphoneDeploymentController extends StudyRuntime<DeviceRegistration> {
// connect to all connectable devices, incl. this phone
await deviceRegistry.connectAllConnectableDevices();

_executor!.initialize(deployment!, deployment!);
_executor.initialize(deployment!, deployment!);
measurements.listen((dataPoint) => _samplingSize++);

// set up coverage heart beat measurements
if (coverageFrequency > 0) {
Timer.periodic(
Duration(minutes: coverageFrequency),
(_) => executor?.addMeasurement(
(_) => executor.addMeasurement(
Measurement.fromData(Coverage(frequency: coverageFrequency))));
}

Expand Down Expand Up @@ -241,14 +241,14 @@ class SmartphoneDeploymentController extends StudyRuntime<DeviceRegistration> {

info('$runtimeType - Starting data sampling...');
super.start();
if (start) _executor!.start();
if (start) _executor.start();
}

/// Stop the sampling.
@override
Future<void> stop() async {
info('$runtimeType - Stopping data sampling...');
_executor!.stop();
_executor.stop();
super.stop();
}

Expand All @@ -269,7 +269,7 @@ class SmartphoneDeploymentController extends StudyRuntime<DeviceRegistration> {
@override
Future<void> remove() async {
info('$runtimeType - Removing deployment from this smartphone...');
executor?.stop();
executor.stop();
await dataManager?.close();

await eraseDeployment();
Expand All @@ -286,7 +286,7 @@ class SmartphoneDeploymentController extends StudyRuntime<DeviceRegistration> {
void dispose() {
info('$runtimeType - Disposing ...');
saveDeployment();
executor?.stop();
executor.stop();
dataManager?.close().then((_) => super.dispose());
}
}

0 comments on commit c294101

Please sign in to comment.