After another Event
after(a) holds once an Event of Rule a has Ended. On its own this stays true forever, so it is narrowed:
.within(duration): the most recent Event ofaEnded at most that long ago..unless(b, c, ...): no Event ofborchas been Confirmed since the most recent Event ofaEnded.
Like every reference to another Rule, a must be added before the Rule that refers to it.
A window after the door
A cold room's door is open from minute 10 to minute 12, and once more at minute 60. Its temperature is above 8 °C from minute 15 to minute 25, soon after the first opening, and from minute 100 to minute 110, long after the second. ExcursionAfterDoor is an excursion within a window after the door was open.
The live chart and its controls need JavaScript. The tables show the Events at the default parameters.
The site cannot run the default parameters: (JavaScript) TypeError: Cannot read properties of undefined (reading 'length')
import static io.github.romanhaendler.rbed.Conditions.*;
import io.github.romanhaendler.rbed.*;
import java.time.Duration;
import java.util.Map;
Channel door = Channel.named("door");
Channel temp = Channel.named("temp");
Rule doorOpen = Rule.named("DoorOpen").when(door.above(0.5));
Rule excursionAfterDoor = Rule.named("ExcursionAfterDoor")
.when(after(doorOpen).within(Duration.ofMinutes(30)).and(temp.above(8)));
Detector detector = Detector.builder()
.rules(doorOpen, excursionAfterDoor)
.build();
for (int m = 0; m <= 150; m++) { // one Sample a minute
detector.push(m * 60_000L, Map.of(
door, m >= 10 && m < 12 || m == 60 ? 1.0 : 0.0,
temp, m >= 15 && m < 25 || m >= 100 && m < 110 ? 10.0 : 4.0));
}
detector.close();
The window is measured from where DoorOpen Ended, not from where it started. At the default of 30 minutes, the first door opening Ended at minute 12, so the window lasts until minute 42 and covers the first excursion: ExcursionAfterDoor runs from 15 to 25. The second door opening Ended at minute 61, 39 minutes before the second excursion starts, so that excursion is not attributed to the door.
Things to try
- Widen the window to 45 minutes: the second excursion counts too, but only until minute 107. From then on the door opening lies more than 45 minutes back, and
ExcursionAfterDoorEnds although the temperature stays above 8 °C until minute 110. - Narrow the window to 5 minutes: the first excursion is cut short in the same way, at minute 18.
Interruptions: unless
Rule lift = Rule.named("Lift").when(weight.above(500));
Rule maintenance = Rule.named("Maintenance").when(serviceMode.above(0.5));
Rule liftSinceService = Rule.named("LiftSinceService").when(after(lift).unless(maintenance));
LiftSinceService holds once a Lift has Ended, until a Maintenance Event is Confirmed. Interrupting Events are named explicitly with unless rather than implied, so a sequence means exactly what it says. ADR-0002 explains why.
The Pulse Channels page uses after(...).within(...) for errors after a deployment, and the Building services example for a compressor that restarts too soon.
Reference
- after: sequences in the README, the canonical text
- After in the Javadoc
Methods used: Channel.named, Rule.named, Rule.when, Expression.above, Conditions.after, After.within, Condition.and, Detector.builder, Detector.Builder.rules, Detector.Builder.build, Detector.push, Detector.close, After.unless.