Alarms Service

The Alarms Service (gva-alarms) is the register-side runtime that converts LRU-reported conditions into platform alarms, keeps the Alarm Register, and drives crew annunciation. It implements the Def Stan 23-009 Alarms Service Specification v3.0.

Overview

The Alarms Service handles:

  • Subscribing to alarm conditions raised by LRUs (subsystems) across the platform
  • Converting condition transitions into the platform Alarm state machine
  • Persisting the Alarm Register across power cycles
  • Publishing the platform alarm category taxonomy (Warning / Caution / Advisory)
  • Driving Annunciation LDM events (audio + visual) for crew stations
  • Processing operator commands: Acknowledge, Clear, Annotate, Override, Remove Override
  • Responding to every command via the Def Stan 23-009 Command Response Protocol (CRP)

The service is a headless daemon backed by PostgreSQL / PostGIS. All inter-process traffic is DDS; every DDS interaction is defined by an IDL contract in the shipped Reference Model.

Roles on the wire

graph LR subgraph "LRUs (subsystems)" LRU1[Engine LRU] LRU2[Weapon LRU] LRU3[Tank LRU] end subgraph "Alarms Service" SVC[gva-alarms] DB[(PostGIS
Alarm Register)] end subgraph "HMI tier" HMI[gva-hmi] POPUP[Popup +
Annunciation] end LRU1 -->|C_Alarm_Condition| SVC LRU2 -->|C_Alarm_Condition| SVC LRU3 -->|C_Alarm_Condition| SVC LRU1 -.->|"C_Alarm_Condition_Specification
(optional)"| SVC SVC --> DB SVC -->|C_Alarm| HMI SVC -->|C_Alarm_Category_Definition| HMI SVC -->|C_Annunciation_startEvent
C_Annunciation_stopEvent| POPUP HMI -->|C_Alarm_acknowledge
C_Alarm_clearAlarm
C_Alarm_annotate
C_Alarm_Condition_override
C_Alarm_Condition_removeOverride| SVC SVC -->|Command Response| HMI

Ownership:

Actor Publishes Subscribes
LRU C_Alarm_Condition, optionally C_Alarm_Condition_Specification
Alarms Service C_Alarm, C_Alarm_Category_Definition, C_Alarm_Condition_Specification (fallback), Annunciation events, CRP responses C_Alarm_Condition, C_Alarm_Condition_Specification, the five command topics
HMI The five command topics C_Alarm, C_Alarm_Category_Definition, Annunciation events

The alarms service is the sole publisher of C_Alarm. LRUs never publish alarms directly — they publish conditions.

Alarm categories

The platform recognises three alarm categories, matching Def Stan 23-009 Table 3. The alarms service publishes a C_Alarm_Category_Definition sample for each on startup so consumers discover the category taxonomy from the wire.

Category Re-annunciation Override allowed Acknowledge required Typical use
Warning Every 15 minutes No Yes Immediate crew action required — safety or mission critical
Caution Every 2 hours Yes Yes Attention needed — degraded capability
Advisory Not re-annunciated No No Information — no immediate action needed

Re-annunciation intervals and the override rule are configurable per platform in alarm_specifications.json.

The service enforces the Def Stan 23-009 category gates:

  • GVA_ALM_9 — Acknowledge is a no-op on Advisories.
  • GVA_ALM_11 — Override is accepted only on Cautions.

Attempts to override a Warning or Advisory are rejected via CRP with the appropriate error code.

Conditions vs alarms

The v3.0 specification distinguishes two lifecycles:

  • Alarm Condition (C_Alarm_Condition) — an LRU-owned fact. "The engine is above 120 °C" is a condition. The LRU publishes it as Active when the fact becomes true and Inactive when it becomes false. Conditions have specifications (C_Alarm_Condition_Specification) describing category, text and classification.
  • Alarm (C_Alarm) — a register-side event. When the alarms service sees a condition go Active it raises an alarm: allocates an alarm ID, records it to the Alarm Register, publishes C_Alarm, and starts crew annunciation. Alarms have state that changes in response to operator commands and underlying condition transitions.

An LRU only ever sees C_Alarm_Condition. Only the alarms service and HMI see C_Alarm.

Alarm state machine

The alarms service state chart matches Def Stan 23-009 §3.4.3:

stateDiagram-v2 [*] --> Active_Unacknowledged : Condition goes Active Active_Unacknowledged --> Active_Acknowledged : Ack command (Warning/Caution) Active_Unacknowledged --> Resolved : Condition goes Inactive Active_Acknowledged --> Resolved : Condition goes Inactive Active_Unacknowledged --> Cleared : Clear command Active_Acknowledged --> Cleared : Clear command Resolved --> Cleared : Clear command (or auto after policy) Cleared --> [*]

Notes:

  • Advisory alarms transition straight from Active_Unacknowledged to Resolved when their condition clears — no Ack step.
  • Re-annunciation — while a Warning or Caution is in Active_Unacknowledged, the annunciation is repeated at the category's re-annunciation interval until the crew acknowledges it.
  • Override — Cautions may be overridden while their condition is still Active. Override suppresses annunciation and is cancelled by the Remove Override command. Overrides are cleared on service restart (crew are re-annunciated on power-on).
  • Cleared is a final wire sample, not a DDS dispose. The Cleared --> [*] transition above is a state-machine end state, not a wire-level removal of the alarm instance — the service publishes one final C_Alarm sample with A_currentState=Cleared and does not dispose/unregister the DDS instance. A late-joining TRANSIENT_LOCAL subscriber (e.g. a log tool that connects after the alarm was cleared) will still see the Cleared sample as the alarm's current state, not observe it disappear from the Alarm Register feed.

Alarm sequence

sequenceDiagram participant LRU as LRU participant SVC as Alarms Service participant HMI as HMI participant Op as Operator Note over LRU: Fault detected LRU->>SVC: C_Alarm_Condition (Active) SVC->>SVC: Look up specification
(LRU spec > override > fallback) SVC->>SVC: Allocate alarm ID
(sequential, service-owned) SVC->>SVC: Persist to Alarm Register SVC->>HMI: C_Alarm (Active_Unacknowledged) SVC->>HMI: C_Annunciation_startEvent
(audio + visual) HMI->>Op: Popup + annunciation Op->>HMI: Acknowledge button HMI->>SVC: C_Alarm_acknowledge SVC->>HMI: CRP response (success) SVC->>HMI: C_Annunciation_stopEvent SVC->>HMI: C_Alarm (Active_Acknowledged) Note over LRU: Fault resolved LRU->>SVC: C_Alarm_Condition (Inactive) SVC->>HMI: C_Alarm (Resolved)

Alarm Register persistence

The Alarm Register is persisted to PostGIS on every state transition (Def Stan 23-009 §7.4 / GVA_ALM_88). After a power cycle the alarms service:

  1. Restores every Active_* alarm and its owning condition from the database.
  2. Clears any Override flags so the crew is re-annunciated.
  3. Continues allocating alarm IDs above the highest restored value.

Persistence requires PostGIS. Without it, the service still runs but the register starts empty on every restart and a warning is logged; this is not a spec-compliant deployment.

Platform configuration file

alarm_specifications.json is a policy overlay loaded at startup. It is not an authoritative alarm catalogue — a well-behaved LRU that publishes its own C_Alarm_Condition_Specification overrides everything in the file.

Resolution order (highest to lowest precedence):

  1. -c/--config=<path> on the command line.
  2. /etc/gva/alarms/alarm_specifications.local.json — operator override. Never shipped by the package, so it is never overwritten on upgrade. Use this to customise the alarm policy without editing the package-owned default in place.
  3. /etc/gva/alarms/alarm_specifications.json — the packaged default, installed by the gva-alarms-service package. Overwritten unconditionally on every upgrade.
  4. Dev-tree fallbacks — only relevant when running an unpacked build out of build/bin without installing.

If none of the search paths resolve, the service logs No alarm specifications file found - using defaults and continues with built-in defaults.

Top-level sections:

{
  "alarmCategories":     [ /* Warning / Caution / Advisory + re-annunciation intervals */ ],
  "alarmConditionSpecifications": [ /* Legacy inline catalogue; treated as an implicit `fallbacks[]` */ ],
  "fallbacks":           [ /* Specs to publish when no LRU spec has been observed within 10 s */ ],
  "disabled":            [ /* Condition IDs the service refuses to raise alarms for */ ],
  "overrides":           [ /* Category remaps: LRU said Caution, this platform says Warning */ ]
}

alarmCategories[]

Overrides the shipped C_Alarm_Category_Definition samples:

{
  "categoryId": 90001,
  "name": "Warning",
  "description": "Critical issues requiring immediate crew attention",
  "reannunciationTimeoutMinutes": 15,
  "annunciationType": "audio_visual"
}

categoryId must be above the 0–9,999 registry-reserved range (Def Stan 23-009 §3.2.3 / GVA_PCRS_003).

fallbacks[] — safety net for silent LRUs

Ten seconds after startup the service walks the fallback catalogue and publishes a C_Alarm_Condition_Specification for any condition ID that hasn't been described by an LRU. This ensures late-joining HMIs and log consumers see specification samples for every condition the platform can raise, even when the LRU firmware is old or minimal.

If the LRU publishes its own spec before or after the fallback fires, the LRU's spec is authoritative from that point forward.

disabled[] — quiet a chatty LRU

Condition IDs listed in disabled[] are dropped at ingress. No C_Alarm is created, no annunciation is fired, no CRP response is emitted (nothing was commanded). Use this to gag an LRU that raises nuisance alarms in a specific deployment without changing the LRU firmware.

overrides[] — reclassify an LRU condition

An override remaps an incoming condition's effective category:

{ "conditionId": 15501, "categoryId": 90001 }

Use this when an LRU classifies a condition at (say) Caution but on this specific platform it should be a Warning. The override wins even when the LRU publishes its own C_Alarm_Condition_Specification.

Operator commands

Five DDS command topics are subscribed by the alarms service. Each carries a T_CommandHeaderType per the Def Stan 23-009 Command Response Protocol (CRP) and receives a matching T_CommandResponseType reply on Alarms__CommandResponseType.

Topic Effect
C_Alarm_acknowledge Marks a Warning or Caution as Active_Acknowledged; silences its annunciation.
C_Alarm_clearAlarm Transitions any alarm to Cleared (operator override of the condition state).
C_Alarm_annotate Attaches free-text crew annotation to an alarm.
C_Alarm_Condition_override Marks a Caution's condition as overridden — suppresses further annunciations.
C_Alarm_Condition_removeOverride Cancels an override.

Authorisation. The service does not enforce crew-role authorisation on commands. Every HMI is expected to enforce Def Stan 23-009 §3.3.1.2 Table 4 (Crew Role Authorisations) itself, by enabling or disabling the on-screen buttons per the operator's current crew role. See the HMI Crew Role Manager for details.

The service does enforce category gates: Acknowledge is silently accepted-and-ignored on Advisories (GVA_ALM_9); Override is rejected with a CRP error on Warnings and Advisories (GVA_ALM_11).

Annunciation

The alarms service is the state-machine truth for annunciation but delegates rendering to the Annunciation LDM per §5.1.3 / §7.1.2.

  • The service publishes a catalogue of C_Annunciation_Definition, C_Audible_Tone_Definition and C_Visual_Annunciation_Definition samples at startup (TRANSIENT_LOCAL, so late-joining subscribers receive them on discovery).
  • When an alarm enters Active_Unacknowledged the service publishes C_Annunciation_startEvent on the appropriate audio + visual annunciation instances.
  • Only one annunciation per modality is active at a time (GVA_ALM_34 §7.3.2.4). If a higher-priority alarm arrives, the service stops the current annunciation and starts the new one.
  • The HMI's AnnunciationManager renders whatever the service says to render.

The default Warning tone is a two-frequency alternating pattern (800 Hz + 1000 Hz) per GVA_ALM_58. Caution and Advisory have no audio tone by default — they are visual-only (annunciationType: "visual" in alarmCategories[]).

HMI display

Alarm popup styles

The GVA HMI displays alarm popups with colour-coded category indicators:

Warning Caution Advisory
Warning Caution Advisory
Warning Caution Advisory
Immediate action required Operator awareness needed Informational

When multiple alarms are queued, the display indicates pending items:

Queued Alarms

Alarms table view

Press F14 (Alarms) on the HMI to display the full alarms table, showing every active alarm sorted by category and time. Columns are Time, Category, State, Source (the raising resource's registered identity), and Message — see HMI — Alarms for the full column reference:

Alarms Table View

DDS quality of service

Every alarms topic is set up via the LDM DDS wrapper library so QoS is resolved by pattern, not per-topic. The alarms service uses:

Message Pattern History Reliability Durability
C_Alarm eAlarm KeepLast(256) Reliable TransientLocal
C_Alarm_Condition eAlarm KeepLast(256) Reliable TransientLocal
C_Alarm_Category_Definition eSpecification KeepLast(64) Reliable TransientLocal
C_Alarm_Condition_Specification eSpecification KeepLast(64) Reliable TransientLocal
Command topics + CRP responses eCommand KeepLast(256) Reliable Volatile
Annunciation events eCommand KeepLast(256) Reliable Volatile

TransientLocal durability guarantees that a late-joining HMI receives every currently-active alarm on discovery, not just alarms raised after it connected.

Database maintenance CLI

Two one-shot recovery actions are exposed on the gva-alarms binary. Both perform the requested action at startup, then the service continues normal boot; there is no separate one-shot systemd unit.

Destructive — no confirmation prompt

Both --db-truncate and --db-clear execute their delete the moment the process starts. There is no --yes interlock and no "are you sure?" prompt. The flag alone is the confirmation.

Never wire either flag into the ExecStart= line of the systemd unit — you will silently wipe the Alarm Register on every reboot. These flags are for interactive operator use only.

Flag Deletes Preserves Effect on running fleet
--db-truncate[-days N] (default 90) Fully-closed alarms (is_resolved=true AND is_acknowledged=true) whose resolve_time is older than the cutoff, plus alarm_history audit rows of the same age Every active/unresolved alarm; every partially-closed alarm; the schema and indexes None — GVA_ALM_14 clear normally removes a closed alarm's row already; this only recovers rows orphaned by a crashed LRU or service instance
--db-clear Every row from every alarms-managed table (alarms, alarm_conditions, alarm_history) Schema, indexes Full factory reset of the Alarm Register. Every LRU re-raises its alarms fresh on next annunciation; there is no specification file to re-publish from (alarms are not configuration data, unlike the registry)

--db-truncate and --db-clear are mutually exclusive; passing both together aborts with exit code 2 before any rows are touched. A failed database connection aborts with exit code 4; a failed delete aborts with exit code 5 — in both cases no partial action is left running and the service does not proceed to normal boot.

Typical use cases:

  • Dev / test: after a batch of simulated alarms accumulates during a test run, --db-truncate clears the stale closed entries without disturbing anything still active.
  • Crash recovery: an LRU or the service itself crashed mid-clear, leaving closed alarms that were never garbage-collected; --db-truncate sweeps them up on the next start.
  • Factory refurbishment: on a returned vehicle, --db-clear gives a completely empty Alarm Register — every LRU re-raises its current state from scratch on next annunciation.

Both actions log every row count they delete, per table, to journald. Example:

[Alarms-DB] ✓ Purged 2 stale closed alarm(s)
[Alarms-DB] ✓ Purged 0 stale alarm_history row(s)
[Alarms-DB] ✓ purgeStaleAlarms: 2 row(s) deleted (older than 2026-08-31T05:24:52Z)
[gva-alarms] --db-truncate complete: 2 row(s) deleted. Continuing normal service boot.

For per-row surgery (clear a single alarm without touching anything else) use the operator-facing DDS command instead — the alarm's own clear/acknowledge lifecycle already removes its row once fully closed (GVA_ALM_14).

Deployment

The alarms service ships as gva-alarms-service (systemd unit gva-alarms.service). Ordering:

  1. postgresql.service
  2. gva-db-init-service postinst provisions the gva_alarms_db role/schema (via gva-db-init.sh, once, at install/upgrade)
  3. gva-registry.service
  4. gva-alarms.service

The platform configuration file path is set via the -c / --config command-line option (ExecStart=/usr/bin/gva-alarms --domain=0 ...), not an environment variable.

Common environment overrides (see the shipped /etc/default/gva-alarms, sample at /usr/share/doc/gva-alarms-service/gva-alarms.env.example):

Variable Purpose
ALARMS_DB_HOST / ALARMS_DB_PORT / ALARMS_DB_NAME / ALARMS_DB_USER / ALARMS_DB_PASSWORD PostgreSQL connection overrides for the Alarm Register
GVA_ALARM_REANN_WARNING_MIN / GVA_ALARM_REANN_CAUTION_MIN Force re-annunciation intervals in minutes (lab / CI only)
GVA_ALARM_REANN_CHECK_MS Sweep interval for the re-annunciation timer (lab / CI only)

Troubleshooting

The HMI shows no alarms even though the LRU is publishing

  • Confirm the LRU is publishing C_Alarm_Condition (not C_Alarm). Under v3.0 only the service publishes C_Alarm.
  • Confirm the LRU's DDS domain matches the alarms service's LDM_DOMAIN_ID.
  • Check that the condition ID is not listed in disabled[] in alarm_specifications.json.
  • Use astutedds-discovery-dump -d <domain> to confirm the LRU and service participants see each other and that the QoS on C_Alarm_Condition matches (Reliable / TransientLocal).

Alarms don't survive a service restart

  • The Alarm Register requires PostGIS. Confirm systemctl status postgresql reports active.
  • Confirm the alarms service's PostgreSQL credentials in /etc/default/gva-alarms are valid.
  • Check the journal for [GVA-Alarms] GVA_ALM_88: restored N alarms on start.

An LRU classifies a condition wrong for this platform

  • Add an entry to overrides[] in alarm_specifications.json mapping the condition ID to the desired category ID. The override wins even when the LRU publishes its own spec.

Duplicate or repeated annunciations

  • Re-annunciation is by design for unacknowledged Warnings and Cautions (§GVA_ALM_30 / GVA_ALM_32). The default intervals are 15 minutes / 2 hours. Acknowledge the alarm to silence it, or override the condition (Cautions only).

Specification references

  • Def Stan 23-009 Alarms Service Specification v3.0 — §3.4.2 (condition state machine), §3.4.3 (alarm state machine), §5.1.3 / §7.1.2 (Annunciation LDM delegation), §5.3.4 (category definitions), §7.3.2.4 (single-annunciation-per-modality), §7.4 (Alarm Register persistence).
  • Def Stan 23-009 Command Response Protocol — all five command topics + CRP responses.
  • Def Stan 23-009 §3.2.3 / GVA_PCRS_003 — registry-reserved identifier band (0–9,999).