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.