Skip to content

EventDetection: query events by alarm state (getActiveEvents / getUnacknowledgedEvents) #277

Description

@HanSur94

Problem / motivation

The detected-event store carries a complete ISA-18.2 alarm-state model, but offers no way to query events by that state.

Each Event knows its alarm state:

  • IsOpen (libs/EventDetection/Event.m:38) — true while the violating condition still persists (EndTime = NaN).
  • ack-status — derived from AckedAt (Event.m:43); the canonical predicate is at Event.m:137.
  • computeDisplayState() (Event.m:125-148) — returns the four-state product 'unacked-active' | 'acked-active' | 'acked-cleared' | 'unacked-cleared'.

EventStore already has a growing query familygetEvents() (EventStore.m:97), getEventsForTag() (:156), plus the filed getEventsInRange(t0,t1) (#225) and getEventsBySeverity/getEventsByCategory (#228) — and a full acknowledgement subsystem (acknowledgeEvent() :337, getAckRecords() :322). But there is no query that filters by alarm state. Verified: grep -rniE "getUnack|getOpenEvent|getActiveAlarm|getEventsByState" libs/ --include="*.m" returns nothing.

So the two most common alarm-management questions have no store-level primitive:

  • "What alarms are currently active?" (still in violation — IsOpen)
  • "What's still unacknowledged?" (the operator hasn't seen it yet)

Today a caller must pull getEvents() and hand-filter on IsOpen / AckedAt, re-deriving the exact predicate Event.computeDisplayState already encapsulates — error-prone and duplicated at every call site (the active-alarm board, the Companion NotificationCenterPane, any report).

Proposed feature

Add read-only state-filter getters to EventStore, mirroring the primitive-per-query style of #225/#228:

  • events = getActiveEvents(obj) — events with IsOpen == true (condition still violating).
  • events = getUnacknowledgedEvents(obj) — events where isAcked is false.
  • (optional third) events = getEventsByDisplayState(obj, state) — general selector over the existing four-state vocabulary ('unacked-active', 'acked-active', 'acked-cleared', 'unacked-cleared'), accepting a single state or a cellstr of states. This subsumes the two focused getters but is lower priority; the active-alarm board ('unacked-active') is the high-frequency case.

Rough sketch

  • Lib / class: libs/EventDetection/EventStore.m (single file).
  • Public API:
    active = es.getActiveEvents();           % IsOpen == true
    open   = es.getUnacknowledgedEvents();   % not yet acknowledged
    board  = es.getEventsByDisplayState('unacked-active');  % optional general form
  • Implementation: a pure in-memory filter over obj.events_, reusing the existing getEventsForTag iterate pattern and the in-repo predicates (ev.IsOpen; the isAcked test from Event.m:137; ev.computeDisplayState() for the general form). Return an Event array (empty [] when none), matching the shape of the existing getters. No new state, no schema change.

Value

High. Alarm/threshold ergonomics is an explicitly named sensor-analysis domain gap. "Show me the active alarms" and "show me everything not yet acknowledged" are the primary alarm-management queries for a MATLAB engineer running live monitoring — and the data model already classifies every event, so the only thing missing is the selector. Composes directly with the filed query/summary family (#225/#228/#245) and feeds any active-alarm board view.

Constraints check

  • Toolbox-free: yes — plain array filtering, no toolbox calls.
  • Backward-compatible: yes — purely additive; no existing method changes, serialized stores untouched, no Event/DashboardWidget/Tag contract change.
  • Pure MATLAB/Octave: yes.

Effort estimate

S — one file, reuses an existing iterate pattern and an in-repo predicate.


AI-proposed via /feature-scout — needs a human product decision before implementation.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions