Skip to main content

AuditReportersConfig

Struct AuditReportersConfig 

Source
pub struct AuditReportersConfig {
    pub reporters: Vec<ObjectIdentifier>,
}
Expand description

A bounded set of target READ/WRITE/CREATE/DELETE Reporters sharing one Device recipient.

Reports successful inbound WP/WPM elements, AddListElement/RemoveListElement, AtomicWriteFile, CreateObject/DeleteObject operations, and authorized execution errors. Policy denials and undecoded/unattempted elements remain silent. Successes omit Result; execution failures include the mapped BACnet Error. There is no source-side reporting, forwarding, or durable outbox. Provision the typed recipient on the built-in Device before startup; configure Device routes with device_binding. Startup requires a concrete built-in local Device (ObjectDatabase::local_device: the lowest instance when the database holds several), a provision, and the selected Reporter capability. That Device names this device in every record and owns the recipient; any other Device in the database takes no part. Unresolved configured Device routes permit startup with CONFIGURATION_ERROR. Address choices require direct unicast IPv4 B/IP, on network zero or on this network’s number once it is known (#1460); one naming a network the number in force does not name starts unresolved the same way. The active Device recipient is required/writable; actual local or authorized WP/WPM changes atomically reserve two attempts before commit, independently of ordinary reporting filters: to the old and the new recipient. The new route must be usable. An unavailable old route requires reconfiguration and restart, except an old Address the number does not name: an unconfirmed global broadcast takes its attempt (Clause 12.11.66). Active Device/Reporter membership is protected until quiescence. At most 64 deliveries are active per server. Optional object-owned Maximum_Send_Delay/Send_Now retains ordinary records in a bounded target queue: 256 records/256 KiB globally and 64 records/64 KiB per Reporter. Mandatory records remain immediate. Each send/ACK has one total three-second deadline and no retry. Known local losses use captured, bounded historical contexts; summary filtering remains the documented partial-profile policy. Unconfirmed success proves only transport acceptance. See docs/delayed-target-audit.md.

Audit_Source_Reporter remains false. AV/BV instance-owned overrides apply to target observations. Supported write_local operations share this observer; raw database authoring remains a bypass. Source reporting is a separate profile. Ordinary sensor samples and internal reliability updates never enter this producer. An enabled external write to a Reporter produces one record. Locally configured Monitored_Objects selects ordinary targets by exact object or object type. Omitted selection preserves catch-all behavior; an empty or all-NULL selection reports no ordinary targets. Reporter writes bypass it. Enabled nominal overlaps fault all affected Reporters; only the lowest instance emits, before ordinary filters. Live local setters and aggregate changes use atomic admission; equal configuration is silent. Network selection writes are not supported. See docs/target-audit-reporters.md for selected fallback policies. CREATE/DELETE require their operation bit, count as configuration operations, and ignore the priority filter. Records use the final/candidate created OID or captured deleted OID, with no property, priority, or values; initial values do not generate WRITE records. A failed by-type creation without an assigned, representable OID omits the target; only catch-all or type selection can match. Deleting or replacing the selected Reporter is denied until the target runtime has stopped and released membership protection.

List edits use WRITE, object/property/requested-index identity, no priority, the requested delta as raw Target_Value, and the known pre-image as Current_Value. Empty, structurally invalid, or over-32-octet values are omitted, never wrapped or truncated. Element and framed-list decoding precedes observation; valid execution failures retain the response-mapped Result. Successful no-op removals still report once. AUDIT_CONFIG admits implemented non-Present_Value lists; list services ignore priority filtering and reuse ordinary target selection. AtomicWriteFile uses WRITE and the known target OID, with no property, priority, or values (Table 19-5). AUDIT_CONFIG and AUDIT_ALL admit file writes; priority filtering is irrelevant. Admission follows the service decoder’s acceptance boundary, which refuses octets after the request’s last member. Decoder rejections and configured payload/count budget Aborts remain silent. An inbound WriteGroup reports WRITE (Table 19-5) once per Channel it writes, as a WriteProperty of that Channel’s Present_Value at the priority used, with the requester as source and no invoke ID; a Channel write the mutation authorizer denied makes none (#1318). A Channel’s Present_Value is commandable (Clause 12.53.5), so its records, a WriteProperty’s included, carry the priority and Audit_Priority_Filter applies to them (Clause 19.6.3): one at a disabled priority is dropped.

READ covers completed, unsegmented RP/RPM responses, one record per returned property outcome in result order, including inline RPM errors. Read values, comments, and priorities are always omitted. READ requires its operation bit; AUDIT_CONFIG excludes Present_Value. RPM’s existing result budget bounds provisional intents, which are discarded on whole-request failure. Admission follows release of the read guard and uses the same captured delivery, optional delay and bounded resource-loss policy.

use bacnet_objects::{audit::AuditReporterObject, database::ObjectDatabase,
    device::{DeviceConfig, DeviceObject}};
use bacnet_server::server::{AuditReportersConfig, BACnetServer, DeviceBinding};
use bacnet_types::{bitstring::AuditOperationFlags, enums::{AuditLevel,
    AuditOperation, ObjectType}, primitives::ObjectIdentifier, constructed::BACnetRecipient};
let mut db = ObjectDatabase::new();
let recipient = ObjectIdentifier::new(ObjectType::DEVICE, 200)?;
let mut device = DeviceObject::new(DeviceConfig::default())?;
device.provision_audit_recipient(BACnetRecipient::Device(recipient))?;
db.add(Box::new(device))?;
let mut reporter = AuditReporterObject::new(1, "Target writes")?;
reporter.set_audit_level(AuditLevel::AUDIT_ALL)?;
let mut operations = AuditOperationFlags::empty();
operations.insert(AuditOperation::WRITE);
reporter.set_auditable_operations(operations)?;
reporter.set_issue_confirmed_notifications(true)?;
db.add(Box::new(reporter))?;
let mut server = BACnetServer::bip_builder().database(db)
    .audit_reporters(AuditReportersConfig {
        reporters: vec![ObjectIdentifier::new(ObjectType::AUDIT_REPORTER, 1)?],
    })
    .device_binding(DeviceBinding::local(recipient, [127, 0, 0, 1, 0xBA, 0xC1])?)?
    .build().await?;
server.stop().await?;

Fields§

§reporters: Vec<ObjectIdentifier>

Between one and 64 distinct concrete target Reporter identifiers. Startup validates and canonicalizes them by instance; this is a local bound.

Trait Implementations§

Source§

impl Clone for AuditReportersConfig

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for AuditReportersConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more