T07: Event Schemes
Turn a machine state tag into stoppage events with reasons, then get downtime minutes onto the interval grid.
What you will build: a stoppage event scheme on a real state tag, with an enumerated reason, and a downtime measure that sums correctly.
Time: about 40 minutes.
You need: T02 completed. This is the most important tutorial in the track — nearly everything analytically interesting in Infohub builds on events.
Step 1 — Look at the state tag first#
The simulator's filler has a state tag, FL001.State, with these values:
| Value | State |
|---|---|
0 |
Idle |
10 |
Setup |
20 |
Running |
21, 22, 23 |
Faults |
30 |
CIP (cleaning) |
Create a retrieved measure for it so you can see the behaviour: in the Filler 1 metric, add Machine State — Retrieved, Tag interval, tag FL001.State, unit state.
Chart it, or look at its values, and watch how it moves over a day. Never configure a trigger without looking at the signal first. How often does it change? Does it bounce? What values does it actually take?
Step 2 — Create the enumeration#
Before the event scheme, create the reason list. A categorical attribute must be an enumeration, or analysis drowns in spelling variants.
In the Toolbox, create an enumeration called Stoppage Reason with options and colours:
| Option | Colour |
|---|---|
| Mechanical failure | Red |
| Electrical failure | Red |
| Label jam | Red |
| Product shortage | Amber |
| Changeover | Amber |
| Planned maintenance | Blue |
| Cleaning (CIP) | Blue |
| No demand | Grey |
| Other | Grey |
Nine options — short enough to choose from. Colours assigned deliberately: red for unplanned failures, blue for planned interventions, grey for things that are not plant problems. Those colours will flow into every chart of this attribute automatically.
Step 3 — Create the event scheme#
In the Model view, on the Filler 1 folder, create an event scheme called Stoppage.
Settings:
| Setting | Value | Why |
|---|---|---|
| Refresh Offset | a few hours | So late-arriving data is captured |
| Archive Age / Purge Age | comfortably beyond your reporting horizon | Purge is irreversible |
| Index Interval | Daily | Numbers stoppages within each day |
| Backfill | leave unset for now | Verify the trigger before building history |
Do not backfill yet. Backfilling before the trigger is proven produces a long history of wrong events that then has to be cleared. Run forward first, check the events, then backfill.
Step 4 — Add the start trigger#
A stoppage starts when the machine leaves the running state.
Add a start trigger on the Simulator connection, tag FL001.State:
| Property | Value |
|---|---|
| Trigger | When the condition becomes true |
| Condition | = is not available for "not equal", so use the comparator that expresses "below running" — condition < with value 20 |
| For Period (s) | 25 |
For Period is the most important property here. Real signals bounce. Without a hold time, a momentary dip generates a stoppage event every few minutes, and a hundred spurious two-second stoppages a day drown the genuine ones.
Set it just below the shortest stoppage you care about. If stoppages under thirty seconds do not matter, twenty-five seconds removes an enormous amount of noise and loses nothing.
Step 5 — Add the end trigger#
A stoppage ends when the machine runs again.
Add an end trigger on the same tag:
| Property | Value |
|---|---|
| Trigger | When the condition becomes true |
| Condition | = with value 20 |
| For Period (s) | 25 |
Start and end are separate triggers, configured independently. That is deliberate — and it means the two failure modes are independent too. A start that fires with an end that never does leaves the event open forever, and every duration above it grows without limit.
Step 6 — Add the attributes#
Add three attributes to the scheme:
| Attribute | Type | Retrieval | Notes |
|---|---|---|---|
Reason |
Enumeration | Manually entered | Bound to Stoppage Reason |
Duration (min) |
Value | Calculated | Period.Duration.TotalMinutes |
State Code |
Value | Retrieved from segments | Reads FL001.State over the event |
Duration (min) is worth noticing: the period in scope is the event, so its duration is available directly. No source needed, one expression, and it works for an event of any length.
State Code is retrieved over the event's own span rather than over a calendar interval — which is the capability that makes event analysis in Infohub much less work than it looks. The fault code that caused the stoppage comes along automatically.
Step 7 — Deploy and verify#
Deploy, and let it run for a few hours.
Then check the events properly. This is the step that separates a working event scheme from one that produces plausible nonsense:
- Count. Does the number of stoppages per day look like what the plant would report?
- Boundaries. Pick three events and compare their start and end times against the state tag's values.
- Open events. Any event with no end? That is an end-trigger problem.
- Duplicates. Two events for one occurrence? A start-trigger problem.
- Durations. Do the stoppage durations across a day plus the running time add up to roughly a day? Much more means overlapping events; much less means gaps.
If you have far too many short events, increase For Period and try again.
Step 8 — Get downtime onto the interval grid#
Events are only useful once they reach ordinary measures. Create an event-aggregated measure in Filler 1:
| Field | Value |
|---|---|
| Name | Downtime Minutes Hourly |
| Interval | Hour(s) |
| Event scheme | Stoppage |
| Anchor | Active Duration |
| Unit | min |
| Format | 0.0 |
Active Duration is the only anchor that sums correctly. There are fourteen anchors. Active Duration attributes only the portion of each event that fell inside each interval, so the values across an interval sum to at most the interval's length.
Try Event Duration (Start) instead and see what happens: an eight-hour stoppage beginning at 22:00 puts all eight hours into the 22:00 hour. You get eight hours of downtime in a one-hour period, and any availability calculation built on it goes below zero.
For anything that becomes a percentage, use Active Duration.
Step 9 — Calculate availability#
Now the payoff. In Filler 1:
| Field | Value |
|---|---|
| Name | Availability Hourly |
| Retrieval type | Calculated |
| Interval | Hour(s) |
| Unit | % |
| Format | 0.0 '%' |
| Dependencies | Downtime Minutes Hourly |
Period.Duration.TotalMinutes == 0 ? 0
: (Period.Duration.TotalMinutes - (Measure_<downtimeId>.Value ?? 0))
/ Period.Duration.TotalMinutes * 100
Using Period.Duration.TotalMinutes rather than hard-coding 60 means it is correct at every interval and survives the daylight-saving days that are twenty-three or twenty-five hours long.
Check the values. They should be between 0 and 100. If they are not, the anchor is wrong.
Step 10 — Build an event table#
Create an Event Based Table with the Event Based Table constructor, drop the Stoppage scheme on it, and put it on a dashboard.
You now have one row per stoppage with its start, end, duration, reason, and state code. This is where an operator checks whether an event was captured correctly, and it is where the reason gets entered — make the Reason column editable by using an Event Based Form instead if you want entry on the same view.
What you have learned#
Events describe what was happening. Intervals cannot; a number alone cannot say whether a low hour was a breakdown, a changeover, or no demand.
Chart the trigger tag before configuring the trigger.
For Period is essential. Without a hold time, real signals produce hundreds of spurious events.
Start and end are independent triggers. An end that never fires leaves events open and every duration wrong.
Enumerate categorical attributes. Free text cannot be grouped, and no downstream cleverness fixes it.
Attributes can be retrieved over the event's own span — average, peak, and final values per event, with no per-event configuration.
Active Duration is the anchor that sums. Use it for anything that becomes a percentage.
Verify events against reality before building analysis on them.
Try this before moving on#
The Reason attribute is manually entered, so it will be blank until someone fills it in — and a Pareto chart whose biggest bar is "unspecified" is a statement about data capture, not about the plant.
Build a measure that counts what proportion of stoppages have a reason recorded, express it as a percentage, and put it on the dashboard. A visible "reasons captured: 62%" changes behaviour faster than asking, and it tells you whether your analysis is trustworthy yet.
Next: T08: Measure Limits — making values judge themselves.