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;}deviceManageris 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,
streamisnulland the probe collects nothing. Measurement.fromDatawraps theMugSipand stampssensorStartTimewith now. If the device has its own timestamp, pass it as the second argument (microseconds since epoch), asESenseSensorProbedoes.
Choose the base class by how data arrives
Section titled “Choose the base class by how data arrives”| 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.