rbed

Counting Events

count(a) is the number of Events of Rule a Confirmed so far, an Expression like any other. .within(duration) counts only those Confirmed in a sliding window ending now:

Rule run = Rule.named("Run").when(power.above(500)).forDuration(Duration.ofSeconds(30));
Rule frequentStarts = Rule.named("FrequentStarts")
    .when(count(run).within(Duration.ofHours(1)).above(3));
Rule serviceDue = Rule.named("ServiceDue").when(count(run).above(10_000));

An Event counts from the moment it is Confirmed, so a running Event is included.

Frequent starts

A machine's power is sampled once a minute. It runs for five minutes from minutes 10, 30, 45, 60, 150 and 200. A Run needs 30 seconds above 500 W, so each one is Confirmed at the next Sample, a minute after its start. FrequentStarts holds while more than the limit of Runs were Confirmed within the window.

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 power = Channel.named("power");

Rule run = Rule.named("Run").when(power.above(500)).forDuration(Duration.ofSeconds(30));
Rule frequentStarts = Rule.named("FrequentStarts")
    .when(count(run).within(Duration.ofMinutes(60)).above(3));
Detector detector = Detector.builder()
    .rules(run, frequentStarts)
    .build();

int[] starts = {10, 30, 45, 60, 150, 200};   // each run lasts five minutes
for (int m = 0; m <= 240; m++) {   // one Sample a minute
  double watts = 0;
  for (int start : starts) if (m >= start && m < start + 5) watts = 800;
  detector.push(m * 60_000L, Map.of(power, watts));
}
detector.close();

At the defaults, an hour's window and a limit of 3:

  • The count rises by one each time a Run is Confirmed: 1 at minute 11, 2 at 31, 3 at 46.
  • At minute 61 the fourth Run is Confirmed, while it is still running. The count is 4, more than 3, and FrequentStarts starts.
  • At minute 72 the Run Confirmed at minute 11 lies more than an hour back and drops out of the window. The count falls to 3, and FrequentStarts Ends.
  • The later Runs are too far apart to count up again.

above(3) means more than 3, so it takes the fourth start. Without within, as in ServiceDue, the count only grows.

Things to try

  • Narrow the window to 30 minutes: no four starts fall into it, and FrequentStarts never holds.
  • Lower the limit to 2: the third Run, Confirmed at minute 46, is enough. FrequentStarts runs from 46 to 92, where the second Run drops out of the window.

The Building services example counts a compressor's starts the same way.

Reference

Methods used: Channel.named, Rule.named, Rule.when, Expression.above, Rule.forDuration, Conditions.count, EventCount.within, Detector.builder, Detector.Builder.rules, Detector.Builder.build, Detector.push, Detector.close.