Skip to main content

bacnet_objects/event_enrollment/
state.rs

1use bacnet_types::enums::{EventState, PropertyIdentifier};
2use bacnet_types::primitives::{ObjectIdentifier, PropertyValue};
3
4/// Effective object, property, and optional array index that own an Event
5/// Enrollment object's private evaluation state.
6pub type EventEnrollmentMonitoredSource = (ObjectIdentifier, PropertyIdentifier, Option<u32>);
7
8/// A delayed Event Enrollment transition, counting down its delay.
9///
10/// The enrollment counterpart of the intrinsic detectors'
11/// [`PendingTransition`](crate::event::PendingTransition), kept as a distinct
12/// type because the driving mechanism differs: the server evaluator advances
13/// `remaining` once per *evaluation pass* (the `event_enrollment_task`
14/// interval, configurable via #133), whereas the intrinsic detectors tick on
15/// a fixed one-second task and seed from per-write probes. The Clause 13.3
16/// delay semantics are shared — the observable `Event_State` holds at the
17/// confirmed state while the countdown runs, a reverted condition cancels
18/// without firing, and a redundant qualifying observation never re-seeds — but the
19/// two implementations do not share code across the objects/server boundary.
20///
21/// In-memory only: like the intrinsic detectors' pending state and baselines,
22/// this is not persisted; a device restart re-evaluation starts from the
23/// confirmed `Event_State`, which is the same restart semantics the
24/// intrinsic-reporting path ships.
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct EventEnrollmentPending {
27    /// The event state the algorithm indicated and will enter when the
28    /// countdown elapses.
29    pub state: EventState,
30    /// Evaluation passes remaining before the transition fires; seeded with
31    /// the direction-appropriate delay (pTimeDelay for offnormal targets,
32    /// pTimeDelayNormal — else pTimeDelay — for NORMAL), converted from
33    /// seconds by the evaluator as `ceil(delay_secs / interval_secs)`.
34    pub remaining: u32,
35    /// Identity of the indicating condition, per algorithm. CHANGE_OF_STATE
36    /// uses one identity for condition (a)'s set-membership check and a
37    /// value-specific identity for condition (c)'s sustained-value check.
38    /// CHANGE_OF_BITSTRING uses the masked monitored bytes. Algorithms whose
39    /// delay applies to the threshold condition itself (OUT_OF_RANGE,
40    /// FLOATING_LIMIT, CHANGE_OF_VALUE) use `0`; the target identifies them.
41    pub condition: u64,
42    /// Fingerprint of the `Event_Parameters` (framed encoding) plus the
43    /// effective `Time_Delay_Normal` in force when this countdown was seeded.
44    /// The evaluator re-reads its parameters every pass; a mismatch cancels
45    /// the in-flight countdown and re-gates from the current parameters —
46    /// no partial countdown is resumed across a parameter change.
47    pub params_fingerprint: u64,
48}
49
50/// Algorithm-side evaluation state owned by an Event Enrollment object.
51///
52/// Not BACnet properties: none of the three slots maps to a Clause 12.12
53/// property (nor to the Table 12-14 `Time_Delay_Normal`, which is
54/// configuration and lives on the object directly). Clause 13.3 assigns the
55/// baseline's initialization and the countdown's existence to local matters,
56/// so they are reachable only through the internal trait channel
57/// ([`BACnetObject::enrollment_eval_state_internal`](crate::traits::BACnetObject::enrollment_eval_state_internal) /
58/// [`BACnetObject::set_enrollment_eval_state_internal`](crate::traits::BACnetObject::set_enrollment_eval_state_internal)),
59/// mirroring the `set_event_state_internal` precedent (issue #130).
60#[derive(Debug, Clone, Default, PartialEq)]
61pub struct EventEnrollmentEvalState {
62    /// Delayed transition in flight, if any.
63    pub pending: Option<EventEnrollmentPending>,
64    /// CHANGE_OF_VALUE detection baseline. Clause 13.3.3 retains the sample
65    /// from a NORMAL indication for subsequent comparisons until the next
66    /// NORMAL indication replaces it. Initialization before that first
67    /// indication is implementation-defined: here it is `None` until the
68    /// first sample, which establishes a baseline without a transition.
69    pub cov_baseline: Option<PropertyValue>,
70    /// Domain-tagged identity of the monitored value behind the most recent
71    /// OFFNORMAL transition. CHANGE_OF_STATE condition (c) requires a
72    /// re-indication only for a different alarm value; retaining the BACnet
73    /// datatype keeps equal numeric values from different domains distinct.
74    pub last_offnormal_value: Option<u64>,
75}