rbed

The latest Event

latest(a) gives access to the most recent Confirmed Event of Rule a, whether still running or Ended:

  • .min(x), .max(x), .mean(x): its Aggregates of Channel x, so far if it is running. Rule a aggregates x for this automatically.
  • .duration(): its duration in milliseconds, up to now if it is running.

Each is an Expression, undefined while there has been no Event of a. This relates the present to an earlier Event.

A partial set-down

A crane lifts a load of 800 kg from 10 s to 40 s and sets it down to 300 kg in between, from 25 s to 30 s. Then it lifts 600 kg from 60 s to 90 s and sets it down to 350 kg from 75 s to 80 s. LoadLifted has an End Condition, so a set-down does not End it. PartialSetDown holds while the weight is below a fraction of the latest lift's maximum.

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.util.Map;

Channel weight = Channel.named("weight");

Rule loadLifted = Rule.named("LoadLifted").when(weight.above(500)).endWhen(weight.below(50));
Rule partialSetDown = Rule.named("PartialSetDown")
    .when(during(loadLifted).and(weight.below(latest(loadLifted).max(weight).times(0.5))));
Detector detector = Detector.builder()
    .rules(loadLifted, partialSetDown)
    .build();

for (int s = 0; s <= 110; s++) {   // one Sample a second
  double kg = s >= 25 && s < 30 ? 300
      : s >= 10 && s < 40 ? 800
      : s >= 75 && s < 80 ? 350
      : s >= 60 && s < 90 ? 600
      : 0;
  detector.push(s * 1_000L, Map.of(weight, kg));
}
detector.close();

At the default fraction of 0.5:

  • Before 10 s there has been no lift, and latest(loadLifted).max(weight) is undefined.
  • During the first lift latest reads that lift, whose maximum is 800 kg. The set-down to 300 kg is below 400 kg, and PartialSetDown runs from 25 s to 30 s.
  • Between the lifts latest still reads the first one, which has Ended, but during(loadLifted) does not hold.
  • From 60 s latest reads the second lift. Its maximum is 600 kg, so its set-down to 350 kg is not below 300 kg, although it would be below half of the first lift's 800 kg.

Things to try

  • Raise the fraction to 0.6: the second set-down counts too. 350 kg is below 360 kg, and PartialSetDown runs from 75 s to 80 s.
  • Lower it to 0.3: neither set-down is below 240 kg or 180 kg, and there is no PartialSetDown.

A cycle taking too long

.duration() of a running Event grows with time, so a Rule can detect a long Event while it is still running:

Rule cycle = Rule.named("Cycle").when(spindle.above(0.5));
Rule slowCycle = Rule.named("SlowCycle")
    .when(during(cycle).and(latest(cycle).duration().above(Duration.ofMinutes(2).toMillis())));

The Cranes example uses PartialSetDown with lifting, overload and classifying a load.

Reference

Methods used: Channel.named, Rule.named, Rule.when, Expression.above, Rule.endWhen, Expression.below (double, Expression), Conditions.during, Condition.and, Conditions.latest, LatestEvent.max, Expression.times, Detector.builder, Detector.Builder.rules, Detector.Builder.build, Detector.push, Detector.close, LatestEvent.duration.