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}