Skip to content

ISA-18.2 Alarm Connector

The ISA-18.2 connector implements the alarm management lifecycle defined by the ANSI/ISA-18.2 standard (Management of Alarm Systems for the Process Industries). It is a processor that consumes Meddle payloads, evaluates user-defined alarm conditions, and emits a new payload every time an alarm changes state — augmented with alarm metadata such as priority and current state.

Connector Types:

  • Isa182 - Stateful alarm processor (evaluates conditions, tracks state per alarm)

The connector is placed in the industrial/ category because alarm management is a foundational requirement for process control, batch manufacturing, and SCADA-driven plants.

  • ✅ ISA-18.2 alarm state machine (normal, unacknowledged, acknowledged, return-unacknowledged)
  • ✅ MXL expression language for arbitrary alarm conditions
  • ✅ Per-alarm priority (low, medium, high, urgent)
  • ✅ Deadband hysteresis to suppress flapping near a threshold
  • ✅ Configurable on-delay and off-delay timers (in milliseconds)
  • ✅ Emits a payload only on state transitions (avoids noise)
  • ✅ Standard _alarm_* metadata keys for downstream routing/alerting
{
"type": "Isa182",
"config": {
"alarms": [
{
"name": "high_temperature",
"condition": "temperature > 80",
"priority": "high"
}
]
}
}
{
"type": "Isa182",
"config": {
"alarms": [
{
"name": "high_temperature",
"condition": "temperature > 80",
"priority": "high",
"setpoint": 80,
"deadband": 2.0,
"delayOn": 5000,
"delayOff": 10000
}
],
"shelveTimeout": 3600000,
"maxShelves": 25
}
}
{
"type": "Isa182",
"config": {
"alarms": [
{
"name": "high_pressure",
"condition": "pressure > 10.0",
"priority": "urgent",
"delayOn": 2000
},
{
"name": "low_flow",
"condition": "flow_rate < 5.0",
"priority": "medium",
"delayOn": 10000
},
{
"name": "tank_overflow",
"condition": "tank_level > 95",
"priority": "high",
"setpoint": 95,
"deadband": 1.0
}
]
}
}

A required array of alarm definitions. At least one alarm is required.

{
"alarms": [
{
"name": "high_temp",
"condition": "temperature > 80",
"priority": "high"
}
]
}

A unique identifier for the alarm. Used as the _alarm_name value in emitted payloads.

{
"name": "compressor_1_high_temp"
}

Recommended convention: <asset>_<measurement>_<condition> (e.g. pump_3_low_pressure).

An MXL expression evaluated against each incoming payload. When the result is true, the alarm is considered active.

{
"condition": "temperature > 80 AND pressure < 5"
}

Examples:

{ "condition": "temperature > 80" }
{ "condition": "vibration_rms >= 0.7" }
{ "condition": "tank_level < 10 OR tank_level > 95" }
{ "condition": "(motor_running == true) AND (current > 12.5)" }

The condition is parsed at startup; an invalid expression rejects the connector configuration before runtime.

Severity used for downstream routing. Must be one of:

  • low
  • medium
  • high
  • urgent
{
"priority": "urgent"
}

Hysteresis applied around the alarm threshold to suppress flapping.

{
"setpoint": 80,
"deadband": 2.0
}
  • setpoint - The nominal threshold value (informational; used together with deadband)
  • deadband - The hysteresis band. When the condition transitions from inactive to active, it stays active until the underlying value crosses below setpoint - deadband

Recommended values: 1-5% of the operating range to avoid spurious transitions on noisy signals.

On-delay in milliseconds. The condition must stay active continuously for this long before the alarm transitions to unacknowledged.

{
"delayOn": 5000
}

Recommended values:

  • Fast processes: 500-2000ms
  • Standard process alarms: 5000-15000ms
  • Trend alarms: 30000ms+ (30s)

Off-delay in milliseconds. The condition must remain inactive continuously for this long before the alarm transitions to rtn_unacknowledged.

{
"delayOff": 10000
}

A longer off-delay keeps an alarm visible long enough for operators to acknowledge it.

{
"shelveTimeout": 3600000,
"maxShelves": 25
}
  • shelveTimeout - Default duration (ms) an alarm may be shelved
  • maxShelves - Maximum number of simultaneously shelved alarms

These parameters reflect ISA-18.2 shelving constraints and are forwarded to downstream UI/management tooling.

The connector implements the ISA-18.2 state machine. Each alarm holds one of the following states:

StateMeaning
normalCondition is inactive; no operator attention required
unacknowledgedCondition went active; operator has not acknowledged
acknowledgedOperator acknowledged while the condition is still active
rtn_unacknowledgedCondition returned to normal, but the prior alarm was never acknowledged

A new payload is emitted on every state transition.

When an alarm changes state, the original payload is copied and augmented with the following keys:

{
"...original fields...": "...",
"_alarm_name": "high_temperature",
"_alarm_state": "unacknowledged",
"_alarm_priority": "high",
"_alarm_timestamp": "2026-05-20T10:14:33.123456789Z"
}

Field reference:

  • _alarm_name - Matches the name from the alarm definition
  • _alarm_state - Current state (normal, unacknowledged, acknowledged, rtn_unacknowledged)
  • _alarm_priority - Priority from the alarm definition
  • _alarm_timestamp - RFC 3339 nanosecond UTC timestamp of the transition
DataPayload → Isa182 → (on state change) → DataPayload + _alarm_* metadata
→ (no state change) → silently absorbed

Example:

Input stream (1Hz):

{ "temperature": 78.0 }
{ "temperature": 81.0 }
{ "temperature": 82.0 }
{ "temperature": 79.0 }
{ "temperature": 78.5 }

With alarm high_temperature: temperature > 80, delayOn: 0, delayOff: 0:

  • Sample 1 (78.0): condition false, state remains normal, no emission
  • Sample 2 (81.0): condition true, state → unacknowledged, payload emitted
  • Sample 3 (82.0): condition still true, no state change, no emission
  • Sample 4 (79.0): condition false, state → rtn_unacknowledged, payload emitted
  • Sample 5 (78.5): condition still false, no state change, no emission
{
"type": "Isa182",
"config": {
"alarms": [
{
"name": "reactor_high_temp",
"condition": "reactor_temperature > 150",
"priority": "urgent",
"setpoint": 150,
"deadband": 5,
"delayOn": 3000,
"delayOff": 10000
}
]
}
}
{
"type": "Isa182",
"config": {
"alarms": [
{
"name": "compressor_overload",
"condition": "motor_current > 25 AND oil_pressure < 2.0",
"priority": "urgent",
"delayOn": 5000
},
{
"name": "compressor_vibration",
"condition": "vibration_rms > 0.7",
"priority": "high",
"setpoint": 0.7,
"deadband": 0.05,
"delayOn": 10000
},
{
"name": "compressor_temp_drift",
"condition": "discharge_temp > 95",
"priority": "medium",
"delayOn": 30000
}
]
}
}
{
"type": "Isa182",
"config": {
"alarms": [
{
"name": "tank_low_level",
"condition": "tank_level < 10",
"priority": "high",
"setpoint": 10,
"deadband": 2,
"delayOn": 5000,
"delayOff": 30000
},
{
"name": "tank_high_level",
"condition": "tank_level > 90",
"priority": "high",
"setpoint": 90,
"deadband": 2,
"delayOn": 5000,
"delayOff": 30000
}
],
"shelveTimeout": 3600000,
"maxShelves": 10
}
}

Problem: The condition appears to evaluate to false even when the underlying data should activate it

Solutions:

  1. Confirm the field name in the condition matches the payload exactly (case-sensitive)
  2. Check the data type — temperature > 80 will fail if temperature arrives as a string. Insert a Transform upstream to coerce types
  3. Verify the upstream connector is actually delivering payloads to the processor (check the dataflow with a Log or Console writer)

Problem: A noisy signal repeatedly oscillates around the threshold, generating many transitions

Solutions:

  1. Add a deadband of 1-5% of the operating range
  2. Increase delayOn so brief excursions are ignored
  3. Apply a MovingAverage or EWMA upstream to smooth the input

Problem: The alarm is no longer active, but the state never returns to normal

Solutions:

  1. ISA-18.2 requires explicit acknowledgement before returning to normal. The rtn_unacknowledged state is the standard path when the condition clears before acknowledgement
  2. Acknowledgement is typically driven from an HMI or alerting tool — wire one up that updates the alarm state in your downstream system

Problem: Connector fails to start with ErrIsa182ConditionEval

Solutions:

  1. Verify the condition parses with MXL syntax — comparisons use >, <, >=, <=, ==, !=
  2. Boolean connectives are AND, OR, NOT
  3. Wrap complex sub-expressions in parentheses

1. Use Deadbands Aggressively on Noisy Sensors

Section titled “1. Use Deadbands Aggressively on Noisy Sensors”

Even a small deadband (1-2% of range) drastically reduces alarm volume in real plants.

[
{ "priority": "urgent", "delayOn": 1000 },
{ "priority": "high", "delayOn": 5000 },
{ "priority": "medium", "delayOn": 15000 },
{ "priority": "low", "delayOn": 30000 }
]

Urgent alarms should fire quickly; lower-priority alarms can tolerate longer confirmation windows.

Downstream alerting often pivots on _alarm_name. Treat alarm names as part of your public schema; don’t rename them lightly.

4. Pair with a Router for Priority-Based Escalation

Section titled “4. Pair with a Router for Priority-Based Escalation”

Route by _alarm_priority to different alerting channels (urgent → SMS, high → email, medium → dashboard only).

The standard recommends ≤ 6 alarms per hour per operator on average. Use deadbands, delays, and consolidated alarm conditions to stay within that envelope.

OpcuaReader → Isa182 → Router → ┬─ Alert (urgent → SMS)
├─ Alert (high → email)
└─ InfluxDb2Writer (audit log)
  1. OpcuaReader: Pulls process variables from a PLC at 500ms cadence
  2. Isa182: Evaluates all configured alarms; emits payloads only on state change
  3. Router: Branches on _alarm_priority
  4. Alert (urgent): Sends SMS via the notification channel
  5. Alert (high): Sends email
  6. InfluxDb2Writer: Audits all alarm transitions for compliance

Predictive Maintenance Combined with Alarm Triggering

Section titled “Predictive Maintenance Combined with Alarm Triggering”
ModbusReader → Predictive → Isa182 → Alert
  1. ModbusReader: Reads vibration and temperature
  2. Predictive: Computes trend and remaining useful life
  3. Isa182: Triggers on vibration_rms_rul < 168 (less than 7 days of useful life left)
  4. Alert: Notifies maintenance
  • Trigger - Simpler condition-based emission without state machine
  • Alert - Send alarm payloads to notification channels
  • Router - Branch by _alarm_priority
  • Predictive - Pair with predictive RUL for proactive alarming
  • Filter - Pre-filter inputs before alarm evaluation