Skip to content

Commit

Permalink
fix of #384
Browse files Browse the repository at this point in the history
  • Loading branch information
bardram committed Apr 25, 2024
1 parent a46629e commit 901c3ce
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>12.0</string>
</dict>
</plist>
79 changes: 78 additions & 1 deletion carp_mobile_sensing/example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
614880AD1C4CC67E848DA927 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54DCEC08DB968A8730700564 /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
Expand All @@ -29,35 +30,51 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
104D0E6424C0837290F67F81 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
54DCEC08DB968A8730700564 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
8068094DF1F93577809E7560 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B59C28B50DCA6EB3EFE4099A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
614880AD1C4CC67E848DA927 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
64DA65E970D88D66AD0A39AF /* Frameworks */ = {
isa = PBXGroup;
children = (
54DCEC08DB968A8730700564 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
946F60AEF8A91A362AE78D59 /* Pods */ = {
isa = PBXGroup;
children = (
104D0E6424C0837290F67F81 /* Pods-Runner.debug.xcconfig */,
B59C28B50DCA6EB3EFE4099A /* Pods-Runner.release.xcconfig */,
8068094DF1F93577809E7560 /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
Expand All @@ -80,6 +97,7 @@
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
946F60AEF8A91A362AE78D59 /* Pods */,
64DA65E970D88D66AD0A39AF /* Frameworks */,
);
sourceTree = "<group>";
};
Expand Down Expand Up @@ -113,12 +131,15 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
04C507E5D68A96FE73DE9128 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
1808F41538E6B26FEF4525F5 /* [CP] Embed Pods Frameworks */,
0413F5789A0013655AEE1C61 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
Expand All @@ -136,7 +157,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
Expand Down Expand Up @@ -178,6 +199,62 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
0413F5789A0013655AEE1C61 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
04C507E5D68A96FE73DE9128 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
1808F41538E6B26FEF4525F5 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
8 changes: 4 additions & 4 deletions carp_mobile_sensing/example/lib/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ void protocolExample() async {
Measure(type: CarpDataTypes.ACCELERATION_TYPE_NAME),
Measure(type: CarpDataTypes.ROTATION_TYPE_NAME),
],
duration: const IsoDuration(seconds: 1),
duration: const Duration(seconds: 1),
),
phone,
);
Expand Down Expand Up @@ -566,7 +566,7 @@ void protocolExample() async {

// // Collect device info after 30 secs
// protocol.addTaskControl(
// ElapsedTimeTrigger(elapsedTime: IsoDuration(seconds: 30)),
// ElapsedTimeTrigger(elapsedTime: Duration(seconds: 30)),
// BackgroundTask(
// measures: [
// Measure(type: DeviceSamplingPackage.DEVICE_INFORMATION),
Expand All @@ -582,9 +582,9 @@ void protocolExample() async {
// See the PulmonaryMonitor demo app for a full-scale example of how to use
// the App Task model.

// Add a task 1 minute after deployment and make a notification.
// Add a task 1/2 minute after deployment and make a notification.
protocol.addTaskControl(
ElapsedTimeTrigger(elapsedTime: const IsoDuration(seconds: 30)),
ElapsedTimeTrigger(elapsedTime: const Duration(seconds: 30)),
AppTask(
type: BackgroundSensingUserTask.ONE_TIME_SENSING_TYPE,
title: "Elapsed Time - App Task",
Expand Down
16 changes: 8 additions & 8 deletions carp_mobile_sensing/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ class LocalStudyProtocolManager implements StudyProtocolManager {
// Issue #384
protocol.addTaskControl(
PeriodicTrigger(period: const Duration(seconds: 5)),
BackgroundTask(duration: const IsoDuration(seconds: 2), measures: [
Measure(type: DeviceSamplingPackage.DEVICE_INFORMATION)
]),
BackgroundTask(
measures: [Measure(type: DeviceSamplingPackage.DEVICE_INFORMATION)],
),
phone);

// // Collect timezone info every time the app restarts.
Expand Down Expand Up @@ -222,7 +222,7 @@ class LocalStudyProtocolManager implements StudyProtocolManager {
// interval: const Duration(milliseconds: 500)),
// Measure(type: SensorSamplingPackage.ROTATION),
// ],
// duration: const IsoDuration(seconds: 1),
// duration: const Duration(seconds: 1),
// ),
// phone,
// );
Expand Down Expand Up @@ -290,16 +290,16 @@ class LocalStudyProtocolManager implements StudyProtocolManager {
// // add a ConditionalPeriodicTrigger to check periodically
// protocol.addTaskControl(
// ConditionalPeriodicTrigger(
// period: Duration(seconds: 20),
// triggerCondition: () => ('jakob'.length == 5)),
// period: const Duration(seconds: 20),
// triggerCondition: () => ('Jakob'.length == 5)),
// BackgroundTask()
// ..addMeasure(Measure(type: DeviceSamplingPackage.DEVICE_INFORMATION)),
// phone,
// Control.Start);

// // Collect device info after 30 secs
// protocol.addTaskControl(
// ElapsedTimeTrigger(elapsedTime: IsoDuration(seconds: 30)),
// ElapsedTimeTrigger(elapsedTime: const Duration(seconds: 30)),
// BackgroundTask(
// measures: [
// Measure(type: DeviceSamplingPackage.DEVICE_INFORMATION),
Expand All @@ -317,7 +317,7 @@ class LocalStudyProtocolManager implements StudyProtocolManager {

// // Add a task after deployment and make a notification.
// protocol.addTaskControl(
// ElapsedTimeTrigger(elapsedTime: const IsoDuration(seconds: 30)),
// ElapsedTimeTrigger(elapsedTime: const Duration(seconds: 10)),
// AppTask(
// type: BackgroundSensingUserTask.ONE_TIME_SENSING_TYPE,
// title: "Elapsed Time Trigger - App Task",
Expand Down
5 changes: 0 additions & 5 deletions carp_mobile_sensing/lib/runtime/executors/executors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,6 @@ abstract class AggregateExecutor<TConfig> extends AbstractExecutor<TConfig> {
}
return true;
}

/// Close this executor permanently. Rarely used once sensing is started.
Future<void> close() async {
group.close();
}
}

// All of the below executor state machine classes are private and only used
Expand Down
3 changes: 2 additions & 1 deletion carp_mobile_sensing/lib/runtime/executors/probes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ abstract class MeasurementProbe extends Probe {
Future<bool> onStart() async {
getMeasurement().then((measurement) {
if (measurement != null) addMeasurement(measurement);
stop();
// automatically stop this probe after it is done collecting the measurement
Future.delayed(const Duration(seconds: 1), () => stop());
}, onError: (Object error) => addError(error));

return true;
Expand Down
44 changes: 41 additions & 3 deletions carp_mobile_sensing/lib/runtime/executors/task_executors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,18 @@ part of '../runtime.dart';
/// to [Executor.measurements] from a task executor.
abstract class TaskExecutor<TConfig extends TaskConfiguration>
extends AggregateExecutor<TConfig> {
final StreamGroup<ExecutorState> _statesGroup = StreamGroup.broadcast();

/// The [TaskConfiguration] for this task executor.
TConfig get task => configuration!;

/// Returns a list of the running probes in this task executor.
/// Returns a list of the probes in this task executor.
List<Probe> get probes =>
executors.map((executor) => executor as Probe).toList();

/// The combines state event from all [probes] in this task executor.
Stream<ExecutorState> get states => _statesGroup.stream;

@override
bool onInitialize() {
if (task.measures != null) {
Expand All @@ -32,6 +38,8 @@ abstract class TaskExecutor<TConfig extends TaskConfiguration>
if (probe != null) {
executors.add(probe);
group.add(probe.measurements);
_statesGroup.add(probe.stateEvents);

probe.initialize(measure, deployment!);
} else {
warning(
Expand All @@ -49,6 +57,12 @@ abstract class TaskExecutor<TConfig extends TaskConfiguration>

/// Executes a [BackgroundTask].
class BackgroundTaskExecutor extends TaskExecutor<BackgroundTask> {
StreamSubscription<ExecutorState>? _subscription;

/// Are all [probes] in a stopped state?
bool get haveAllProbesStopped =>
!probes.any((probe) => probe.state != ExecutorState.stopped);

@override
Future<bool> onStart() async {
// Early out if no probes.
Expand All @@ -61,14 +75,26 @@ class BackgroundTaskExecutor extends TaskExecutor<BackgroundTask> {
return false;
}

// Listen to stop this background executor when all of its underlying
// probes have stopped - Issue #384
_subscription =
states.where((event) => event == ExecutorState.stopped).listen((_) {
if (haveAllProbesStopped) {
debug(
'$runtimeType - all probes have stopped - stopping this $runtimeType too.');
stop();
}
});

// Check if the device for this task is connected.
if (probes.first.deviceManager.isConnected) {
if (configuration?.duration != null) {
// If the task has a duration (optional), stop it again after this duration has passed.
Timer(
Duration(seconds: configuration!.duration!.toSeconds().truncate()),
Timer(Duration(seconds: configuration!.duration!.inSeconds.truncate()),
() => stop());
}

// Now - finally - we can start the probes.
return await super.onStart();
} else {
warning(
Expand All @@ -77,6 +103,18 @@ class BackgroundTaskExecutor extends TaskExecutor<BackgroundTask> {
return false;
}
}

@override
Future<bool> onRestart() async {
_subscription?.cancel();
return super.onRestart();
}

@override
Future<bool> onStop() async {
_subscription?.cancel();
return super.onStop();
}
}

/// Executes a [FunctionTask].
Expand Down

0 comments on commit 901c3ce

Please sign in to comment.