OEE - Edge Aggregator

The edge app from the FlowFuse OEE worked example — it reads a line's machine signals and publishes its state, one Remote Instance per line. The flow logic is a simple straight line; the choices that matter are packaging it for reuse and treating the data as a stream.

Definition

  • The app — reads a line's machine signals and publishes its state.
  • Design patternsubflow, applied to the whole flow (not to extract an internal seam): the straight-line flow is packaged as one subflow and dropped onto every line, each configured with its own line's PLC tags as per-instance config — the Node-RED side of the Configurable App pattern.
  • Data handlingclassify (the signals are a telemetry stream, read at the poll cadence) → hold the running run/stop counts in context.
  • Runs on — a Remote Instance, one per line.
  • Why this shape — the same complete job runs identically on every line, right next to the equipment, and keeps working if the link drops.

The flow

Edge Aggregator · one subflow, dropped on every linesave tagsload tagscatches (scope)config UIset this line's tagscontexttag configinject / timerpoll tickget configload the tagsPLC readreads those tagscompute statecounts in contextMQTT outpublish line stateCatchscoped to the readcontext readCatch scope · not a wire

Why these choices

  • Subflow, applied whole-flow — the flow itself is a straight line with no seams to extract, so there's no internal pattern to reach for. But because the same complete flow runs on every line, it's packaged as a subflow — reuse across instances is exactly the subflow rung. The pattern is applied to the whole flow, not to a piece inside it.
  • Configured per line — why it's a Configurable App — a config UI node sets this line's PLC tag names into context; a get config node in front of the PLC read loads them, so the one subflow reads different tags on every line without changing the build. That per-line configuration is exactly what makes it a Configurable App.
  • Classify: it's a stream — the signals are telemetry read at the poll cadence, so the latest value matters more than any single earlier one. One read → one compute → one publish per tick; the poll interval already paces it, so there's no fast-in / slow-out to rate-limit.
  • Context for the counts — running run/stop counts live in flow context, not threaded through the wires.
  • Catch the read — a PLC read can time out; a Catch scoped to the read handles a dropped read so it doesn't stall the publish. A Catch node isn't wired from the read — it registers to catch errors in its scope, so the dashed line shows that scope, not a connection. Catching errors is good form, not a per-flow choice.
In one line — a subflow per line: set the tags in a config UI, load them, then poll → read → compute → publish (with a scoped catch); the data call is treating it as a stream and holding the counts in context.