Skip to content

Triggers

File What is in it
domain/core/triggers.dart Every trigger that ships with CAMS
runtime/executors/trigger_executors.dart The matching executors (see Executors)

Triggers are configured via a TriggerConfiguration and define the temporal configuration of a study, i.e., when data sampling is done. CAMS comes with a set of built-in triggers:

Trigger Description
ImmediateTrigger Starts sampling immediately.
OneTimeTrigger Triggers only once during a deployment.
DelayedTrigger Delays sampling for the specified delay measured from sensing start.
ElapsedTimeTrigger Delays sampling for the specified delay measured from study deployment start.
PassiveTrigger Can be started manually with resume and paused with pause.
PeriodicTrigger Runs periodically with a fixed period.
DateTimeTrigger Schedules sampling at a specific date and time.
RecurrentScheduledTrigger Schedules sampling with a recurrent date/time pattern.
CronScheduledTrigger Resumes and pauses sampling based on a cron expression.
SamplingEventTrigger Starts when a sampling event occurs (for example entering a geofence).
ConditionalSampling EventTrigger Resumes/pauses based on the result of a Dart function.
ConditionalPeriodicTrigger Periodically checks if an app-specific condition is met.
RandomRecurrentTrigger Triggers a random number of times within a defined daily period.
UserTaskTrigger Triggers based on the state of a UserTask.
NoUserTaskTrigger Triggers when a certain user task is not on the task list.
AppLifecycleTrigger Triggers when the life cycle of an app changes, as defined in AppLifecycleState.
Kind Triggers
Immediately NoOpTrigger, ImmediateTrigger, OneTimeTrigger, PassiveTrigger
After a delay or interval DelayedTrigger, PeriodicTrigger
At a time DateTimeTrigger, RecurrentScheduledTrigger, CronScheduledTrigger, RandomRecurrentTrigger
On data SamplingEventTrigger, ConditionalSamplingEventTrigger, ConditionalPeriodicTrigger

Triggers are a central part of a StudyProtocol and CAMS allows creating your own triggers and add them to the framework. This is done by the following steps:

  1. Define one or more new Triggers.
  2. Define a TriggerExecutor for each new trigger.
  3. Define and register a TriggerFactory that knows how to create the correct TriggerExecutor based on a specific trigger.

Any trigger should extend the TriggerConfiguration class and implement domain-specific fields that configure this trigger. In the example below, we have defined a RemoteTrigger that listens to resources on a server identified by a URI, and triggers when this resource is available.

/// A trigger that triggers based on event from a remote server.
@JsonSerializable(includeIfNull: false, explicitToJson: true)
class RemoteTrigger extends TriggerConfiguration {
RemoteTrigger({
required this.uri,
this.interval = const Duration(minutes: 10),
}) : super();
/// The URI of the resource to listen to.
String uri;
/// How often should we check the server?
Duration interval;
@override
Function get fromJsonFunction => _$RemoteTriggerFromJson;
factory RemoteTrigger.fromJson(Map<String, dynamic> json) =>
FromJsonFactory().fromJson<RemoteTrigger>(json);
@override
Map<String, dynamic> toJson() => _$RemoteTriggerToJson(this);
}

Trigger configurations are part of a study protocol and hence needs to be serializable to/from JSON.

The trigger only describes when. It is run by a trigger executor, which is described under Executors.