119 lines
5.7 KiB
Markdown
119 lines
5.7 KiB
Markdown
# Alarm Analysis Dashboard
|
||
|
||
A drop-in Ignition Perspective dashboard that turns the **alarm journal** into
|
||
actionable alarm-management metrics: alarm rate, MTTA/MTTR, flood episodes,
|
||
chattering and standing alarms, a Pareto of bad actors, a day/hour heatmap, and
|
||
an overall alarm-health score graded A–F against ISA-18.2 style targets.
|
||
|
||
It reads the journal through `system.alarm.queryJournal` / `system.alarm.queryStatus`
|
||
only. There are **no tags, no named queries, no SQL and no database connection** —
|
||
if the gateway has an alarm journal profile with data in it, the dashboard works.
|
||
|
||
---
|
||
|
||
## Requirements
|
||
|
||
* Ignition **8.1.20+** with the **Perspective** module.
|
||
* An **alarm journal profile** that is receiving data (Gateway → Config → Alarming →
|
||
Journal). Any journal store works; the resource never talks to the database directly.
|
||
* No third-party modules, no Python packages, no gateway scripting configuration.
|
||
|
||
## Install
|
||
|
||
1. In the Designer, open the project you want the resource in and choose
|
||
**File → Import…**, or use **Config → Projects → Import** on the Gateway
|
||
web page to bring the download in as its own project.
|
||
2. Import the resource. Everything lands under namespaced folders, so nothing in
|
||
an existing project is overwritten:
|
||
|
||
| Resource | Location |
|
||
|---|---|
|
||
| Views | `Exchange/AlarmAnalysis/…` |
|
||
| Style classes | `exchange/alarm-analysis/…` |
|
||
| Project library | `exchange/alarmAnalysis/{alarms, calc, fmt}` |
|
||
| Page | `/alarm-analysis` → `Exchange/AlarmAnalysis/Dashboard` |
|
||
|
||
3. **Save** the project.
|
||
4. Open a Perspective session and browse to **`/alarm-analysis`**.
|
||
|
||
That is the whole installation. The dashboard holds all of its own state on the
|
||
`Dashboard` view, so importing it does **not** add session custom properties,
|
||
client tags or global variables to your project.
|
||
|
||
### If you imported into an existing project
|
||
|
||
* The page URL `/alarm-analysis` is added to your project's page configuration.
|
||
If that URL is already taken, change it in **Project Browser → Perspective →
|
||
Page Configuration**; the view path it should point at is
|
||
`Exchange/AlarmAnalysis/Dashboard`.
|
||
* Nothing else in your project is touched — every resource is namespaced.
|
||
|
||
### If you want it on its own page shell
|
||
|
||
Embed `Exchange/AlarmAnalysis/Dashboard` in any view or dock. It takes no
|
||
parameters and sizes itself to its container (design size 1600×900).
|
||
|
||
## Using it
|
||
|
||
| Tab | What it shows |
|
||
|---|---|
|
||
| **Overview** | Headline KPIs vs the previous equal-length period, alarm-rate chart, priority mix, top sources, and plain-language insights. |
|
||
| **Analysis** | Day/hour heatmap, flood episodes, MTTA/MTTR trend, and priority distribution against the ISA 80/15/5 target. |
|
||
| **Bad Actors** | Pareto of the worst offenders plus chattering, standing and fleeting alarm tables. Click a row for the per-source drill-down. |
|
||
| **Journal** | Paged, filtered journal browser with CSV export and a per-event detail popup. |
|
||
|
||
* The **range selector** and **Refresh** in the header set the analysis window.
|
||
* The **filter bar** (Priority / Area / State / Search) applies to every tab except
|
||
Overview, which deliberately stays a plant-wide summary.
|
||
* **Shift Report** renders a plain-text handover summary for the previous shift,
|
||
ready to copy into a log.
|
||
* Clicking a source anywhere drills through to that source in **Bad Actors**;
|
||
clicking a Bad Actors row opens the per-source history popup.
|
||
|
||
## Tuning
|
||
|
||
All thresholds live in one place — `exchange.alarmAnalysis.calc.DEFAULTS`:
|
||
|
||
| Key | Default | Meaning |
|
||
|---|---|---|
|
||
| `target_per_hr` | `6.0` | ISA target alarm rate per operator per hour |
|
||
| `flood_per_10min` | `10` | Activations per 10 min that start a flood episode |
|
||
| `chatter_per_hr` | `10.0` | Re-triggers per hour that mark a source as chattering |
|
||
| `chatter_gap_s` | `120` | Median gap below which re-triggers count as chatter |
|
||
| `fleeting_s` | `10` | Active duration below which an alarm counts as fleeting |
|
||
| `standing_hours` | `24` | Age above which an active alarm counts as standing |
|
||
| `priority_target` | `80/15/5` | ISA low/medium/high priority mix |
|
||
| `health_weights` | see source | Weighting of the five health sub-scores |
|
||
| `max_events` | `50000` | Hard cap on journal rows read per query |
|
||
|
||
Edit the dict in the Designer's script library, or pass an override dict as the
|
||
`opts` argument of any `calc` function.
|
||
|
||
## Script library
|
||
|
||
| Module | Responsibility |
|
||
|---|---|
|
||
| `exchange.alarmAnalysis.alarms` | Talks to `system.alarm`; the only module that does I/O. Entry points used by the views: `getDashboardBundle`, `getJournalPage`, `journalCsv`, `getSourceDetail`, `getEventData`, `getShiftReportText`. |
|
||
| `exchange.alarmAnalysis.calc` | Pure analytics — correlation, binning, floods, chatter, MTTA/MTTR, Pareto, health score. No Ignition API calls, so it is unit-testable. |
|
||
| `exchange.alarmAnalysis.fmt` | Display formatting and the natural-language insight/shift-report text. |
|
||
|
||
Every public function carries a docstring, so the Designer's autocomplete
|
||
documents the API.
|
||
|
||
## Notes and limits
|
||
|
||
* The journal is queried for **twice** the selected window (current plus the
|
||
equal-length prior period) so every KPI can show a delta. A very wide range over
|
||
a busy plant is bounded by `max_events`; when that cap is hit the header shows a
|
||
*truncated* chip.
|
||
* Alarm instances are correlated by journal event id when the journal supplies
|
||
one, and by a per-source active/clear state machine otherwise. The mode in use
|
||
is reported in `bundle.meta.correlation_mode`.
|
||
* "Active now", unacked and shelved counts come from live alarm status, so they
|
||
reflect the present moment rather than the selected window.
|
||
* Scripts are Jython 2.7 compatible (no f-strings, no `typing`, no `statistics`).
|
||
|
||
## License
|
||
|
||
Provided as-is under the terms of the Ignition Exchange.
|