Skip to content

2. Write a probe

A probe reads one source and emits Measurements. The mug pushes a sip whenever it happens, so the fitting base class is StreamProbe: override stream and CAMS subscribes when the study resumes.

/// Emits one [MugSip] measurement every time the mug reports a sip.
class SipProbe extends StreamProbe {
@override
MugDeviceManager get deviceManager => super.deviceManager as MugDeviceManager;
@override
Stream<Measurement>? get stream => deviceManager.isConnected
? deviceManager.mug!.sips.map(
(sip) => Measurement.fromData(
MugSip(temperature: sip.temperature, volume: sip.volume),
),
)
: null;
}
  • deviceManager is set by the registry. The override only narrows its type, so the probe can reach the mug. See step 3.
  • While the mug is not connected, stream is null and the probe collects nothing.
  • Measurement.fromData wraps the MugSip and stamps sensorStartTime with now. If the device has its own timestamp, pass it as the second argument (microseconds since epoch), as ESenseSensorProbe does.
If the source… Extend
pushes events (mug sips, screen on/off) StreamProbe
is read once (device info) MeasurementProbe
is read every N seconds (free memory) IntervalProbe, implement getMeasurement()
streams fast and you want windows or averages PeriodicStreamProbe, BufferingPeriodicProbe, BufferingIntervalStreamProbe, BufferingPeriodicStreamProbe

See Executors for how the probe is started, paused and disposed.