scadaBR Alarm List: Configuring Message-Based Filters

Karen Mitchell4 min read
HMI / SCADAOther ManufacturerTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

In a scadaBR 1.2 project shared by multiple operators, the standard alarm list can expose alarms from every monitored system. That creates an operational risk: an operator can acknowledge an alarm assigned to another system. The supported workaround is to render a separate alarm table with a server-side script, filter events before generating rows, and scope any bulk command to that table.

Understand the Filtering Mechanism

The demonstrated script obtains active events through com.serotonin.mango.db.dao.EventDao, localizes each event message, and includes a row only when the message contains a configured system identifier. This supports alarm separation when messages follow a controlled naming convention such as GGD: Gerador com falha de arrefecimento, TEL: Switch 2, Porta 6 down, or DIS: No-Break em falha.

Decision Supported approach Constraint
Filter by system Search the localized alarm message for a system identifier. Every applicable message must contain a consistent identifier.
Change the filter dynamically Supply the whitelist text from an alphanumeric data point. Validate the resulting text before using it as the filter.
Filter by data source Not established by the available implementation. Do not assume the message-based script provides data-source ownership.
Separate operator actions Give each table its own generated CSS class and scope table commands to that class. A global command can still affect alarms outside the visible table.

Define the Alarm Message Contract

Assign one stable prefix or token to every system and place it in each alarm message. Treat this token as routing data, not free-form descriptive text. A filter for GGD will match any localized message containing that character sequence, so choose tokens that do not occur unintentionally in other messages.

  1. Inventory the systems that require separate alarm views.
  2. Assign a unique system token to each system.
  3. Update the corresponding alarm messages so each contains the correct token.
  4. Configure each operator view with only its assigned token or whitelist value.

If an alphanumeric data point supplies the filter, changing that point can change which alarms the table displays without editing the script. Control who can modify that point because it determines the table's visible scope.

Build the Filtered Server-Side Table

The following core logic reflects the demonstrated implementation. It reads active events, resolves each localized message, and emits a row only when the message contains sequencia.

var eventDao = new com.serotonin.mango.db.dao.EventDao();
var activeEvents = eventDao.getActiveEvents();
var sequencia = "GGD";
var linhas = "";

for (var i = 0; i < activeEvents.size(); i++) {
    var evento = activeEvents.get(i);
    var bundle = new com.serotonin.mango.Common().getBundle();
    var mensagem = evento.getMessage().getLocalizedMessage(bundle);

    if (mensagem.includes(sequencia)) {
        linhas += "<tr>" +
            "<td>" + evento.getId() + "</td>" +
            "<td>" + evento.getActiveTimestamp() + "</td>" +
            "<td>" + evento.getAlarmLevel() + "</td>" +
            "<td>" + mensagem + "</td>" +
            "</tr>";
    }
}

Wrap the generated rows in a table and apply CSS as needed. The available implementation maps alarm levels 0 through 4 to green, blue, yellow, orange, and red flag images respectively. Verify that these level-to-image mappings match the project's intended alarm semantics before deployment.

Do not call the row generator once for all active events and again for unacknowledged active events unless duplicate rows are intentional. An unacknowledged event belongs to both sets and can therefore appear twice. Use one pass and add acknowledgement state as a column or CSS class when both status and visibility are required.

Scope Acknowledge and Silence Commands

Create a unique class for each rendered table using the component identifier:

var uniqueClass = "evttable-" + pointComponent.id;

The demonstrated bulk-acknowledgement selector restricts simulated clicks to visible tick controls inside that table:

document.querySelectorAll(
  "." + uniqueClass + " td > .cmd-btn[src*=tick]:not([style*=hidden])"
).forEach(function (elm) { elm.click(); });

This selector prevents the table control from clicking acknowledgement icons in another table. It does not prove server-side authorization. Confirm that the underlying acknowledgement operation rejects events outside the operator's assigned scope.

The demonstrated silence control calls MiscDwr.silenceAll(). Its call is global rather than scoped through uniqueClass; therefore, do not present it as a per-system command until testing confirms the required boundary or the command is replaced with a scoped implementation.

Verify Filtering and Operator Isolation

  1. Create active alarms containing each configured system token and confirm that every table shows only its assigned messages.
  2. Create a message without a token and one containing a token as an unintended substring; confirm the handling of both cases and revise the message contract if necessary.
  3. Check acknowledged and unacknowledged events for duplicate rows. Each event ID should appear once unless duplication is explicitly required.
  4. From one operator view, acknowledge a displayed alarm and verify that an alarm assigned to another table remains unchanged.
  5. Test any bulk acknowledgement control with multiple tables on the same view and confirm that its selector resolves only inside the generated uniqueClass.
  6. Test silence separately. If MiscDwr.silenceAll() affects alarms outside the operator's system, remove that control from the filtered table.

The server-script APIs shown here were demonstrated in custom scadaBR/Scada-LTS alarm-table work, but the evidence does not establish compatibility across every build. Validate the script in the target scadaBR 1.2 environment before replacing the existing alarm display.

FAQ

How do I filter scadaBR alarms by system?

Add a unique system token such as GGD to each applicable alarm message, localize the event message in the server script, and render the event only when the message contains that token.

Why does my custom scadaBR alarm table show duplicate events?

The script may be processing active events once without filtering and again for unacknowledged status. An active, unacknowledged event satisfies both passes, so generate the table in one pass and display acknowledgement state separately.

Does a filtered alarm table prevent cross-system acknowledgement?

No. Filtering controls which rows are rendered; it does not by itself establish server-side authorization. Scope the UI selector with evttable- plus the component ID and verify that the underlying acknowledgement action cannot modify an event outside the operator's assignment.

Back to blog