LOX Alarm
A single alarm instance, with its lifecycle made explicit.
A deterministic, heap-free C99 runtime object models one Boolean alarm condition: delays, active and return states, acknowledgement, shelving, out-of-service handling, snapshots and transition reasons. Applications own the alarm instances, input logic, clock and operator presentation.
Signal state and operator acknowledgement are distinct
The state model includes NORMAL, ACTIVE, LATCHED_RETURN, SHELVED and OUT_OF_SERVICE. SUPPRESSED exists as a reserved enum, but the documented core has no transition API for it. The alarm receives a Boolean condition; it does not calculate a threshold or read a sensor.
When configured to latch, clearing the input after the off-delay moves to LATCHED_RETURN until acknowledged. If the input becomes true again before acknowledgement, it reactivates. Reason flags and one-shot transition queries allow the caller to publish or display changes.
On-delay filters activation; off-delay stabilizes return
`on_delay_ms` requires the Boolean condition to remain true before activation. `off_delay_ms` requires it to remain false before a return transition. They solve different forms of chatter and are independently configured.
The caller passes a monotonic `uint32_t` millisecond timestamp. Modulo wrap is supported within documented limits; backward jumps greater than half the range are rejected, and a single delay cannot exceed that half-range. Update work is bounded and O(1) for one object.
Silence, acknowledgement and out-of-service have separate meaning
Shelving is bounded by the configured maximum duration. While shelved, the underlying condition continues to be tracked, but activation one-shot flags do not fire in the same way as an unshelved transition. Expiry or explicit unshelving returns to the prior active or latched-return state.
Acknowledgement clears a latched return; it is not an input reset. OUT_OF_SERVICE freezes condition evaluation until the caller returns the instance to service. Force reset returns the live state to NORMAL while preserving lifetime counters.
Encoding helpers do not persist alarm history automatically
The runtime can encode/decode portable snapshot bytes, but it never writes flash or NVRAM itself. The application chooses when to save and where. If a latched-return alarm is not persisted, reboot loses that live state. Snapshot wire bytes use schema identifiers, but cross-version migration policy and storage integrity belong to the integrator.
A snapshot does not include a CRC or torn-write protection. Add an atomic storage scheme and integrity check appropriate to the target medium. A persisted shelved or bypass-like operational state should be reviewed as an application policy decision before restoring it.
State boundaries and snapshots have named tests
The project evidence matrix points to tests for clock wrap and backward-jump rejection, counter saturation, portable snapshot round-trip and corruption rejection, out-of-service freeze behavior, and reset preserving lifetime counters. The test plan also identifies a deterministic fuzz-like invariant test and ASan/UBSan CI configuration.
Those are repository-described checks, not hardware timing measurements or proof of standards conformance. Although the vocabulary references ISA 18.2 and OPC UA Part 9 alarm concepts, the implementation is a documented runtime subset.
An alarm state core, not a certified alarm system
- One Boolean condition per instance; thresholds, hysteresis, filtering and severity are upstream.
- No persistence, event transport, HMI, historian, alarm registry, multi-stage coordination or first-out across instances.
- Snapshot storage integrity, atomicity and cross-version migration are caller responsibilities.
- Same-instance concurrent access needs external synchronization; separate instances can be independent.
- The project explicitly makes no SIL, IEC 61508, IEC 61511, ISO 26262 or other safety certification claim.