Expand description
Bridge alert management (BAM): aggregation, prioritisation and acknowledgement of conditions reported as events.
Domain operations report a condition on every evaluation that finds it
(guidance reports XTE exceeded on each call, traffic raises a CPA alarm on
each assessment). AlertManager turns that stream into one alert per
condition, with a priority, acknowledgement and clearance.
§Alert lifecycle
An event declares its condition via Reportable; the policy assigns a
priority. A classified condition raises an alert keyed by AlertKind
(condition + target, source or sensor). If an alert of that kind is already
standing, it is repeated: its count increments and nothing new is
annunciated. States follow IMO BAM:
AlertState::Active— raised, not acknowledged;AlertState::Acknowledged— acknowledged, condition present;AlertState::Rectified— condition gone, not yet acknowledged;- normal — gone and acknowledged; removed from the list.
A condition ends either by an ending event (fix acquired ends fix lost, a
healthy sensor ends its suspicion, target lost ends its CPA alarm) or by
silence: an alert not repeated within AlertPolicy::rectify_after is
rectified on the next AlertManager::tick.
§Policy
Priority is the vessel’s decision: AlertPolicy is the port,
StandardPolicy a default. XTE exceeded may be a warning in open water
and an alarm in a channel. What counts as a condition is the domain’s:
Reportable is implemented for every event type in the workspace;
applications implement it for their own event unions.
use kinavis_alerts::{AlertChange, AlertManager, AlertPriority, AlertState, StandardPolicy};
use kinavis_kernel::{Distance, EventList, Instant, TargetId, Utc};
use kinavis_traffic::TrafficEvent;
use core::time::Duration;
let mut alerts = AlertManager::new(StandardPolicy::default());
let start = Instant::<Utc>::from_unix_seconds(1_789_000_000);
// Every assessment reports the same target too close; one alert stands.
for second in 0..3 {
let now = start.checked_add(Duration::from_secs(second)).unwrap();
let mut events = EventList::<TrafficEvent>::new();
events.push(TrafficEvent::CpaAlarm {
target: TargetId::new(7),
cpa: Distance::from_cables(3.0)?,
tcpa: Duration::from_secs(600),
at: now,
});
let changes = alerts.ingest(&events, now);
if second == 0 {
assert!(matches!(changes[0], AlertChange::Raised(_)));
} else {
assert!(changes.is_empty());
}
}
assert_eq!(alerts.len(), 1);
let alarm = alerts.alerts()[0];
assert_eq!(alarm.priority(), AlertPriority::Alarm);
assert_eq!(alarm.occurrences(), 3);
// Acknowledged, it stands quietly; when the target is lost it is over.
alerts.acknowledge(alarm.id(), start)?;
assert_eq!(alerts.alerts()[0].state(), AlertState::Acknowledged);
let mut events = EventList::<TrafficEvent>::new();
events.push(TrafficEvent::TargetLost { target: TargetId::new(7), last_seen: start });
let changes = alerts.ingest(&events, start.checked_add(Duration::from_secs(60)).unwrap());
assert!(changes.iter().any(|change| matches!(change, AlertChange::Cleared(_))));
// The lost target is itself a caution, standing on its own.
assert_eq!(alerts.len(), 1);
assert_eq!(alerts.alerts()[0].priority(), AlertPriority::Caution);§Feature flags
std(default) — standard library maths in the kernel.libm— forno_stdtargets:--no-default-features --features libm.serde— serialisation of the value types.
No allocation: the manager holds at most MAX_ALERTS alerts inline and
reports overflow instead of dropping silently.
Structs§
- Alert
- Standing alert.
- Alert
Changes - Changes made by one call, in order.
- AlertId
- Alert identifier, unique while the alert stands.
- Alert
Manager - Standing alerts under a policy.
- Standard
Policy - Default policy for a vessel in open water.
Enums§
- Alert
Change - Alert state change.
- Alert
Kind - Alert key: condition and subject.
- Alert
Priority - Alert priority per BAM, in ascending order.
- Alert
State - Alert state.
- Ended
- Conditions an event ends.
Constants§
- MAX_
ALERTS - Maximum number of standing alerts.
- MAX_
CHANGES - Maximum number of changes reported per call.
Traits§
- Alert
Policy - Priority assignment: a vessel decision, not a domain one.
- Reportable
- Event accepted by the alert board: the condition it reports and the conditions it ends.