Occurrences

Watched conditions of the thing under test, written as a JavaScript expression over the model's channels and judged during a run or always.

View as Markdown

An occurrence registers that the thing under test did something noteworthy. Where an alarm watches the plant and the equipment, an occurrence belongs to the procedure: its edges stay with the run that observed them and also enter the persistent Occurrences timeline of the Events page. Its condition is a JavaScript expression over the model's channels, debounced on both edges and gated by the quality of what it reads. Occurrences live under Process > Models > model > Setup > Occurrences and need the Edit recipes & evaluations permission.

The Occurrences folder

Selecting the Occurrences row opens the folder page ("Watched conditions of the thing under test. Every edge stays with its run when applicable and also enters the persistent Occurrences history.") with one card per occurrence, by name; clicking a card opens it and the X removes it. With none, the page says "No occurrences yet. Add one."

Command What it does Greyed when (situation) Not drawn when (role)
Occurrence (detail bar, folder selected; right-click Add occurrence) Adds Occurrence <n>: severity Warning, armed during procedures, enabled, no message, an empty condition. Selects it. Any unit holds a run, or the runtime is stopped. Without Edit recipes & evaluations.

The occurrence's page

The header carries the name, a pill with the severity (in the severity's own colour) and a Disabled pill when the occurrence is off. Two kinds of notice can stand under it:

  • A caution note when the saved condition does not validate (the draft is still saved; the note says what is wrong, see below).
  • One Evaluation unavailable banner per unit on which the live condition could not be evaluated, as "<unit>: <error>". A unit's diagnostic is written once per unchanged error and cleared when the evaluation succeeds again.

Identity & behavior

Field What it is Values / default Effect
Name The occurrence's name: the tree row, the event label in the run file, the Events timeline and the reports. Free text; Occurrence <n> at creation. Renames the row and what a procedure's checklist calls it.
Severity The weight of an activation. The picker shows each option in the ink its pill will carry. Info, Warning (default), Critical. Colours the pill and the episode wherever it is listed. During a run, an activation of a Warning or Critical occurrence also requests an operating-system notification while the app is hidden or minimized; Info stays in the window.
Armed When the condition is judged. During a procedure (default): only while a run of a procedure that arms it is active, over the recorded rows. Always: also outside runs, by a background watcher reading the unit's bindings live. An Always occurrence needs no procedure to arm it; one armed During a procedure is judged only by the procedures that tick it.
On delay (ms) How long the condition must stay true before Activated is confirmed, at the resolution of the samples. A number of milliseconds; 0 by default. The field takes no negative number: the entry is refused, the note says so under the field, and the previous value comes back. Debounces the rising edge.
Off delay (ms) How long the condition must stay false before Cleared is confirmed. Same; 0 by default. Debounces the falling edge.
Enabled Whether the occurrence arms at all. On by default. A disabled occurrence never arms, in a run or outside one, and never blocks Start.
Message The text recorded and announced with an activation. Free text; empty by default. Travels with every edge into the run file and the journal.

Condition

"A single JavaScript expression returning Bool." The card holds a code editor, the list of the references you may use ("Available channel references: Channels.Ch_1, Channels.Outlet_temperature, …"), and the reminder "During a run the condition reads the recorded datalog columns; the Always watcher reads the unit bindings live. Syntax, missing references and runtime evaluation failures are shown here without treating them as false or signal loss."

A channel is referenced as Channels.<identifier>, where the identifier is the channel's name sanitized: letters and digits survive, every other character becomes _, and a name starting with a digit gains a _ in front. Channels holds only the model's channels and nothing else, so a channel named Math, isNaN or true is still a valid channel name and hides no JavaScript global. A present, good NaN is data you can test with isNaN(Channels.Pv). Examples: Channels.Outlet_temperature > 80, Channels.Door_open && Channels.Heater_on.

The draft is validated as you type, against sample values of each channel's type, and the caution note under the header says what fails:

Note Meaning
"Syntax error: …" The expression does not parse.
"Channel reference 'Channels.X' does not exist in this model." A reference names no channel.
"More than one channel maps to 'Channels.X'." Two channel names sanitize to the same identifier; rename one on the Channels grid.
"The condition must return Bool, but returned <type>." The expression yields something other than true or false.
"Evaluation error: …" The expression throws.

An invalid condition is still saved as a draft. It has consequences elsewhere: an enabled occurrence that fails validation and is armed by a procedure (ticked on it, or armed Always) blocks that procedure's Start, and the procedure's page shows "Occurrence '<name>' is invalid: …"; an invalid Always occurrence does not start its outside-run watcher and leaves one visible diagnostic here instead of repeating it every poll.

Each evaluation runs in a constrained engine (a 500 ms limit, a bounded number of statements and a bounded memory), so a runaway expression fails its evaluation rather than the station.

How an occurrence is judged

During a run the condition is judged over the rows the datalog records, so a channel the procedure's datalog does not record is unavailable to it. A procedure that arms an occurrence over such a channel, or that arms one and records nothing at all, is refused on its own page and at Start: the occurrence would never judge, and the caution note names it. Outside runs, an Always occurrence is judged by a watcher that reads the unit's bindings live. Either judge holds the last confirmed state while any referenced channel is unavailable: only a missing value or a bad quality suspends judging, and a present, good value (a NaN included) is evaluable data. The judge records four transitions: Activated (after the on delay), Cleared (after the off delay), Unavailable (a referenced channel lost its signal) and Restored (every referenced channel is back; the condition is judged again and the applicable delay restarts).

During a run every transition is written to the run file first and then copied, with its run context, into the durable journal on the Events page; outside runs the watcher writes to the journal alone. Starting a run discards the unit's outside-run judge, and leaving the run creates a fresh one, so no activation carries over an unobserved boundary. Edits to the name, message or severity affect only later edges; edits to the condition, the delays, the armed mode or the enabled state start a fresh observation.

Episodes (activation to clear, with any signal-loss interval counted separately) are derived from those edges wherever the app shows them: the Occurrences card of a panel, the Events page, Histories and the reports. An episode's active time is exactly the interval between the two persisted edges, so it excludes the on delay and includes the off delay: the clock starts when the condition has already held for the on delay, and it stops only when the clear is written, after the off delay has run. That is the number a report hands to a third party.

Where an occurrence is used

A procedure's page carries the card Occurrences armed during this procedure, with an "<n> armed" pill and one checkbox per occurrence of the model, by name. Ticking one arms it during that procedure's runs; an occurrence armed Always watches regardless and needs no tick. With no occurrence in the model the card says "No occurrences in this model yet. Add some under the model's Occurrences." See Procedures.

Renaming a channel rewrites that channel's Channels.<identifier> references in every condition of the model; it does not touch strings, comments or a property of the same name on another object.

Remove occurrence

Remove occurrence stands in the detail bar's danger cluster with the occurrence selected, on its right-click menu, and as the X on the folder page's card. It asks first ("Delete occurrence", "This removes the occurrence from the model.") and un-arms the occurrence from every procedure that ticked it. It needs Edit recipes & evaluations and is greyed under the engineering lock and the stopped runtime.

What an occurrence does not do

  • It is not an alarm: it is not acknowledged, it has no priority and it does not watch tags. The plant's alarms are on the Logic page.
  • It fires nothing. An activation is recorded and announced; no action, label or report is attached to it.
  • It cannot read anything but the model's channels: no tag, no variable, no other model.
  • It is not judged per unit differently: one condition serves every unit, over that unit's own bindings or recorded rows.