1use std::collections::HashMap;
8use std::net::Ipv4Addr;
9#[cfg(test)]
10pub(crate) use std::sync::atomic::AtomicBool;
11use std::sync::atomic::Ordering;
12use std::sync::Arc;
13use std::time::Instant;
14
15use bytes::{Bytes, BytesMut};
16use tokio::sync::{mpsc, oneshot, watch, Mutex, RwLock, Semaphore};
17use tokio::task::JoinHandle;
18use tokio::time::Duration;
19use tracing::{debug, warn};
20
21use event_delivery::EventDelivery;
22
23use bacnet_encoding::apdu::{
24 self, encode_apdu, AbortPdu, Apdu, ComplexAck, ConfirmedRequest as ConfirmedRequestPdu,
25 ErrorPdu, RejectPdu, SegmentAck as SegmentAckPdu, SimpleAck,
26 UnconfirmedRequest as UnconfirmedRequestPdu,
27};
28use bacnet_encoding::npdu::NpduAddress;
29use bacnet_encoding::primitives::encode_property_value;
30use bacnet_encoding::segmentation::{
31 duplicate_in_window, max_segment_payload, split_payload, SegmentReceiver, SegmentedPduType,
32};
33use bacnet_network::layer::NetworkLayer;
34use bacnet_objects::database::ObjectDatabase;
35use bacnet_objects::notification_class::{
36 lookup_notification_recipients, resolve_transition_priority_ack,
37};
38use bacnet_services::alarm_event::EventNotificationRequest;
39use bacnet_services::common::BACnetPropertyValue;
40use bacnet_services::cov::COVNotificationRequest;
41use bacnet_services::cov_multiple::COVNotificationMultipleRequest;
42use bacnet_services::who_is::{DeviceInstanceRange, IAmRequest, WhoIsRequest};
43use bacnet_transport::bip::BipTransport;
44use bacnet_transport::port::TransportPort;
45use bacnet_types::enums::{
46 AbortReason, ConfirmedServiceChoice, ErrorClass, ErrorCode, LifeSafetyOperation,
47 NetworkPriority, NotifyType, ObjectType, PropertyIdentifier, RejectReason, Segmentation,
48 UnconfirmedServiceChoice,
49};
50use bacnet_types::error::Error;
51use bacnet_types::primitives::{ObjectIdentifier, PropertyValue};
52use bacnet_types::MacAddr;
53
54use crate::audit_notification::{
55 AuditNotificationAuthorizationContext, AuditNotificationAuthorizer,
56 UnconfirmedAuditNotificationAuthorizationContext, UnconfirmedAuditNotificationAuthorizer,
57 MAX_AUDIT_NOTIFICATIONS, MAX_AUDIT_NOTIFICATION_BYTES,
58};
59pub use crate::cov::{CovCounters, CovPolicy};
60use crate::cov::{
61 CovNotificationKind, CovSubscription, CovSubscriptionSnapshot, CovSubscriptionTable,
62};
63use crate::handlers;
64use crate::life_safety::{LifeSafetyOperationAuthorizationContext, LifeSafetyOperationAuthorizer};
65use confirmed_request_tracker::{
66 ConfirmedRequestAdmission, ConfirmedRequestTracker, PendingConfirmedRequest,
67};
68pub use device_bindings::DeviceBinding;
69use device_bindings::{register_configured_binding, DeviceBindingTable};
70use learned_router_cache::LearnedRouterCache;
71use lso_replay::{LsoAdmission, PendingLsoReplay};
72use notification_transactions::{
73 canonical_direct_peer, canonical_routed_peer, run_notification_under_dcc,
74 run_notification_worker, InitiationRestricted, NotificationTransactions,
75 NotificationWorkerResult,
76};
77use request_services::{DispatchContext, RequestOrigin, RequestServices, UnconfirmedServices};
78use requests::confirmed_response::ResponseTarget;
79use requests::ConfirmedRequestOwnership;
80use segmentation::{ComplexAckParams, SegmentedSendResources};
81
82const MAX_SEG_RECEIVERS: usize = 128;
84
85const MAX_REQUEST_SEGMENTS: usize = 256;
99
100const MAX_SEG_SENDERS: usize = 128;
102
103const SEG_RECEIVER_TIMEOUT: Duration = Duration::from_secs(4);
105
106const MAX_NEG_SEGMENT_ACK_RETRIES: u8 = 3;
108
109const DEFAULT_APDU_SEGMENT_TIMEOUT: Duration = Duration::from_secs(5);
111
112const DEFAULT_APDU_SEGMENT_RETRIES: u8 = MAX_NEG_SEGMENT_ACK_RETRIES;
114
115const DEFAULT_APDU_RETRIES: u8 = 3;
118
119#[derive(Debug, Clone)]
121pub struct TimeSyncData {
122 pub raw_service_data: Bytes,
124 pub is_utc: bool,
126 pub source_mac: MacAddr,
129 pub source_network: Option<NpduAddress>,
131 pub provenance: bacnet_transport::port::TransportProvenance,
134}
135
136mod config;
137pub use config::ServerConfig;
138mod audit_batch_queue;
139mod audit_batch_runtime;
140mod audit_context_preparation;
141mod audit_forwarder;
142#[cfg(test)]
143mod audit_forwarder_tests;
144mod audit_recipient;
145mod audit_recipient_routes;
146mod audit_reporter;
147mod audit_reporter_changes;
148mod audit_send_now;
149mod heap_futures;
150pub use audit_reporter::{valid_bip_audit_address, AuditReportersConfig};
151#[cfg(test)]
152mod audit_reporter_tests;
153
154pub struct ServerBuilder<T: TransportPort> {
156 config: ServerConfig,
157 db: ObjectDatabase,
158 transport: Option<T>,
159 configured_device_bindings: Vec<DeviceBinding>,
160}
161
162impl<T: TransportPort + 'static> ServerBuilder<T> {
163 pub fn database(mut self, db: ObjectDatabase) -> Self {
165 self.db = db;
166 self
167 }
168
169 pub fn transport(mut self, transport: T) -> Self {
171 self.transport = Some(transport);
172 self
173 }
174
175 pub fn device_binding(mut self, binding: DeviceBinding) -> Result<Self, Error> {
177 register_configured_binding(&mut self.configured_device_bindings, binding)?;
178 Ok(self)
179 }
180
181 pub fn reinit_password(mut self, password: impl Into<String>) -> Self {
183 self.config.reinit_password = Some(password.into());
184 self
185 }
186
187 pub fn life_safety_operation_authorizer<F>(mut self, authorizer: F) -> Self
189 where
190 F: Fn(&LifeSafetyOperationAuthorizationContext) -> bool + Send + Sync + 'static,
191 {
192 self.config.life_safety_operation_authorizer = Some(Arc::new(authorizer));
193 self
194 }
195
196 pub fn audit_notification_sink(mut self, sink: ObjectIdentifier) -> Self {
198 self.config.audit_notification_sink = Some(sink);
199 self
200 }
201
202 pub fn audit_notification_authorizer<F>(mut self, authorizer: F) -> Self
204 where
205 F: Fn(&AuditNotificationAuthorizationContext) -> bool + Send + Sync + 'static,
206 {
207 self.config.audit_notification_authorizer = Some(Arc::new(authorizer));
208 self
209 }
210
211 pub fn unconfirmed_audit_notification_authorizer<F>(mut self, authorizer: F) -> Self
213 where
214 F: Fn(&UnconfirmedAuditNotificationAuthorizationContext) -> bool + Send + Sync + 'static,
215 {
216 self.config.unconfirmed_audit_notification_authorizer = Some(Arc::new(authorizer));
217 self
218 }
219
220 pub fn enable_fault_detection(mut self, enabled: bool) -> Self {
228 self.config.enable_fault_detection = enabled;
229 self
230 }
231
232 pub fn enable_event_enrollment(mut self, enabled: bool) -> Self {
234 self.config.enable_event_enrollment = enabled;
235 self
236 }
237
238 pub fn event_enrollment_interval_secs(mut self, secs: u64) -> Self {
241 self.config.event_enrollment_interval_secs = secs;
242 self
243 }
244
245 pub fn segmentation_supported(mut self, segmentation: Segmentation) -> Self {
252 self.config.segmentation_supported = segmentation;
253 self
254 }
255
256 pub fn vendor_id(mut self, id: u16) -> Self {
258 self.config.vendor_id = id;
259 self
260 }
261
262 pub fn discovery_policy(mut self, policy: DiscoveryPolicy) -> Self {
264 self.config.discovery_policy = policy;
265 self
266 }
267
268 pub fn cov_policy(mut self, policy: CovPolicy) -> Self {
271 self.config.cov_policy = policy;
272 self
273 }
274
275 pub async fn build(self) -> Result<BACnetServer<T>, Error> {
277 let transport = self
278 .transport
279 .ok_or_else(|| Error::Encoding("transport not set on ServerBuilder".into()))?;
280 BACnetServer::start_with_clock_mode_and_bindings(
281 self.config,
282 self.db,
283 transport,
284 Some(ClockConfig::default()),
285 self.configured_device_bindings,
286 )
287 .await
288 }
289}
290
291pub struct BipServerBuilder {
293 config: ServerConfig,
294 db: ObjectDatabase,
295 configured_device_bindings: Vec<DeviceBinding>,
296}
297
298impl BipServerBuilder {
299 pub fn interface(mut self, ip: Ipv4Addr) -> Self {
301 self.config.interface = ip;
302 self
303 }
304
305 pub fn port(mut self, port: u16) -> Self {
307 self.config.port = port;
308 self
309 }
310
311 pub fn broadcast_address(mut self, addr: Ipv4Addr) -> Self {
313 self.config.broadcast_address = addr;
314 self
315 }
316
317 pub fn database(mut self, db: ObjectDatabase) -> Self {
319 self.db = db;
320 self
321 }
322
323 pub fn device_binding(mut self, binding: DeviceBinding) -> Result<Self, Error> {
325 register_configured_binding(&mut self.configured_device_bindings, binding)?;
326 Ok(self)
327 }
328
329 pub fn reinit_password(mut self, password: impl Into<String>) -> Self {
331 self.config.reinit_password = Some(password.into());
332 self
333 }
334
335 pub fn life_safety_operation_authorizer<F>(mut self, authorizer: F) -> Self
337 where
338 F: Fn(&LifeSafetyOperationAuthorizationContext) -> bool + Send + Sync + 'static,
339 {
340 self.config.life_safety_operation_authorizer = Some(Arc::new(authorizer));
341 self
342 }
343
344 pub fn audit_notification_sink(mut self, sink: ObjectIdentifier) -> Self {
346 self.config.audit_notification_sink = Some(sink);
347 self
348 }
349
350 pub fn audit_notification_authorizer<F>(mut self, authorizer: F) -> Self
352 where
353 F: Fn(&AuditNotificationAuthorizationContext) -> bool + Send + Sync + 'static,
354 {
355 self.config.audit_notification_authorizer = Some(Arc::new(authorizer));
356 self
357 }
358
359 pub fn unconfirmed_audit_notification_authorizer<F>(mut self, authorizer: F) -> Self
361 where
362 F: Fn(&UnconfirmedAuditNotificationAuthorizationContext) -> bool + Send + Sync + 'static,
363 {
364 self.config.unconfirmed_audit_notification_authorizer = Some(Arc::new(authorizer));
365 self
366 }
367
368 pub fn enable_fault_detection(mut self, enabled: bool) -> Self {
376 self.config.enable_fault_detection = enabled;
377 self
378 }
379
380 pub fn enable_event_enrollment(mut self, enabled: bool) -> Self {
382 self.config.enable_event_enrollment = enabled;
383 self
384 }
385
386 pub fn event_enrollment_interval_secs(mut self, secs: u64) -> Self {
389 self.config.event_enrollment_interval_secs = secs;
390 self
391 }
392
393 pub fn segmentation_supported(mut self, segmentation: Segmentation) -> Self {
400 self.config.segmentation_supported = segmentation;
401 self
402 }
403
404 pub fn vendor_id(mut self, id: u16) -> Self {
406 self.config.vendor_id = id;
407 self
408 }
409
410 pub fn discovery_policy(mut self, policy: DiscoveryPolicy) -> Self {
412 self.config.discovery_policy = policy;
413 self
414 }
415
416 pub fn cov_policy(mut self, policy: CovPolicy) -> Self {
419 self.config.cov_policy = policy;
420 self
421 }
422
423 pub async fn build(self) -> Result<BACnetServer<BipTransport>, Error> {
425 let transport = BipTransport::new(
426 self.config.interface,
427 self.config.port,
428 self.config.broadcast_address,
429 );
430 BACnetServer::start_with_clock_mode_and_bindings(
431 self.config,
432 self.db,
433 transport,
434 Some(ClockConfig::default()),
435 self.configured_device_bindings,
436 )
437 .await
438 }
439}
440
441type TransportCleanup<T> = JoinHandle<(NetworkLayer<T>, Result<(), Error>)>;
442
443pub struct BACnetServer<T: TransportPort> {
445 target_audit: Option<Arc<audit_recipient::TargetAudit<T>>>,
446 config: ServerConfig,
447 discovery_limiter: Arc<DiscoveryLimiter>,
448 #[allow(dead_code)] time_sync_limiter: Arc<TimeSyncLimiter>,
450 _clock: Option<Arc<ServerClock>>,
452 network: Option<Arc<NetworkLayer<T>>>,
455 broadcaster: Arc<broadcaster::BroadcasterState<T>>,
456 transport_cleanup: Option<TransportCleanup<T>>,
457 transport_cleanup_error: Option<String>,
458 network_number_task: Option<JoinHandle<()>>,
459 db: Arc<RwLock<ObjectDatabase>>,
461 cov_table: Arc<RwLock<CovSubscriptionTable>>,
464 cov_counters: Arc<crate::cov::AtomicCovCounters>,
465 #[allow(dead_code)]
467 seg_ack_senders: Arc<segmented_send::SegmentedSendRegistry>,
468 #[allow(dead_code)]
471 seg_send_permits: Arc<Semaphore>,
472 cov_in_flight: Arc<Semaphore>,
475 learned_routers: Arc<Mutex<LearnedRouterCache>>,
477 notification_transactions: Arc<NotificationTransactions>,
479 #[allow(dead_code)]
481 confirmed_request_tracker: Arc<ConfirmedRequestTracker>,
482 device_bindings: Arc<RwLock<DeviceBindingTable>>,
484 comm_state: Arc<CommState>,
486 dcc_timer: Arc<Mutex<crate::server::dcc_timer::TimerSlot>>,
489 dcc_outcomes: Arc<dcc_outcomes::DccOutcomes>,
490 event_suppressions: Arc<event_suppression::EventSuppressions>,
492 mutation_decisions: Arc<crate::mutation::MutationDecisions>,
493 dispatch_task: Option<JoinHandle<()>>,
494 request_tasks: Arc<request_tasks::RequestTasks>,
495 cov_purge_task: Option<JoinHandle<()>>,
496 fault_detection_task: Option<JoinHandle<()>>,
497 event_enrollment_task: Option<JoinHandle<()>>,
498 trend_log_task: Option<JoinHandle<()>>,
499 schedule_tick_task: Option<JoinHandle<()>>,
500 intrinsic_reporting_task: Option<JoinHandle<()>>,
502 binary_lighting_operation_task: Option<JoinHandle<()>>,
505 cov_revisit_task: Option<JoinHandle<()>>,
507 local_mac: MacAddr,
508}
509
510pub struct IAmBroadcaster<T: TransportPort> {
517 state: std::sync::Weak<broadcaster::BroadcasterState<T>>,
518}
519
520impl<T: TransportPort> Clone for IAmBroadcaster<T> {
521 fn clone(&self) -> Self {
522 Self {
523 state: self.state.clone(),
524 }
525 }
526}
527
528impl BACnetServer<BipTransport> {
529 pub fn bip_builder() -> BipServerBuilder {
531 BipServerBuilder {
532 config: ServerConfig::default(),
533 db: ObjectDatabase::new(),
534 configured_device_bindings: Vec::new(),
535 }
536 }
537}
538
539mod clock;
540mod command_runs;
541mod time_sync_policy;
542mod write_group;
543#[cfg(test)]
544pub(crate) use clock::clocked_test_database;
545pub use clock::ClockConfig;
546use clock::ServerClock;
547use time_sync_policy::{request_limiters, TimeSyncLimiter};
548pub use time_sync_policy::{
549 TimeSyncPolicy, TimeSyncRateLimit, TimeSyncSource, TimeSyncSourceRestriction,
550};
551mod binary_lighting_lifecycle;
552#[cfg(test)]
553mod confirmed_issuance_tests;
554mod confirmed_request_tracker;
555mod cov_clock;
556mod cov_encoding;
557mod cov_fanout;
558mod cov_notifications;
559mod cov_notify_context;
560mod cov_snapshot;
561mod dcc_disable_rate;
562pub(crate) mod dcc_outcomes;
563mod dcc_policy;
564mod lso_replay;
565pub use dcc_disable_rate::DccDisableRateLimit;
566mod dcc_timer;
567pub use dcc_outcomes::DccOutcomeCounters;
568pub use dcc_policy::{DccPolicy, DccSource, DccSourceRestriction};
569use dcc_timer::CommState;
570pub use dcc_timer::DccState;
571mod binding_probes;
572mod device_bindings;
573mod discovery;
574#[doc(hidden)]
575pub use discovery::iam_request_for as discovery_iam_for_test;
576pub use discovery::{DiscoveryCounters, DiscoveryPolicy};
577pub(crate) use discovery::{DiscoveryLimiter, PreCheckDecision, WhoHasTarget};
578mod audit_log_purge;
579mod dispatch;
580mod durable_writes;
581mod event_delivery;
582mod event_enrollment_lifecycle;
583mod event_forwarding;
584pub use event_forwarding::MAX_FORWARDED_DESTINATIONS;
585mod event_forwarding_repeats;
586mod event_message_policy;
587pub(crate) mod event_notification_payload;
588mod event_notifications;
589mod event_recipient_route;
590mod event_send;
591mod event_suppression;
592pub use event_suppression::EventNotificationCounters;
593mod received_event_log;
594pub use received_event_log::{RECEIVED_EVENT_LOG_RATE, RECEIVED_EVENT_LOG_SOURCES};
595mod confirmed_answer;
596pub(crate) mod event_timestamp;
597mod handles;
598mod learned_router_cache;
599mod lifecycle;
600mod local_writes;
601mod network_port;
602#[cfg(test)]
603mod network_port_tests;
604pub use confirmed_answer::{CovAckResult, Refusal};
605mod remote_writes;
606pub(crate) use remote_writes::RemoteRequestError;
607mod notification_transactions;
608#[doc(hidden)]
609pub use notification_transactions::{
610 canonical_direct_peer as __endpoint_canonical_direct_peer,
611 canonical_routed_peer as __endpoint_canonical_routed_peer,
612 run_notification_worker as __endpoint_run_notification_worker,
613 AuditFailureContext as __endpoint_AuditFailureContext,
614 AuditFailureQueue as __endpoint_AuditFailureQueue,
615 AuditFailureTicket as __endpoint_AuditFailureTicket,
616 NotificationOperation as __endpoint_NotificationOperation,
617 NotificationReserveError as __endpoint_NotificationReserveError,
618 NotificationTransactions as __endpoint_NotificationTransactions,
619 NotificationWorkerResult as __endpoint_NotificationWorkerResult,
620};
621mod requests;
622#[doc(hidden)]
623pub use requests::endpoint_responder::EndpointResponder as __endpoint_EndpointResponder;
624#[cfg(feature = "sc-tls")]
625mod sc_builder;
626#[cfg(test)]
627pub(crate) use requests::{EXECUTED_CONFIRMED, EXECUTED_UNCONFIRMED};
628#[cfg(test)]
629mod audit_notification_tests;
630#[cfg(test)]
631mod unconfirmed_audit_notification_tests;
632#[cfg(feature = "sc-tls")]
633pub use sc_builder::ScServerBuilder;
634mod responses;
635mod segmentation;
636mod segmented_receive;
637mod segmented_send;
638pub(crate) use segmented_send::*;
639mod request_admission;
640mod rpm_budget;
641pub use rpm_budget::ReadPropertyMultipleBudget;
642mod alarm_summary_budget;
643pub use alarm_summary_budget::GetAlarmSummaryBudget;
644mod atomic_read_file_budget;
645mod atomic_write_file_budget;
646mod read_range_budget;
647pub use read_range_budget::ReadRangeBudget;
648mod event_information_budget;
649pub use event_information_budget::GetEventInformationBudget;
650mod enrollment_summary_budget;
651pub use atomic_read_file_budget::AtomicReadFileBudget;
652pub use atomic_write_file_budget::AtomicWriteFileBudget;
653pub use enrollment_summary_budget::GetEnrollmentSummaryBudget;
654#[cfg(test)]
655mod atomic_read_file_tests;
656#[cfg(test)]
657mod atomic_write_file_tests;
658#[cfg(test)]
659mod enrollment_summary_tests;
660mod request_peer;
661mod request_services;
662mod request_tasks;
663pub use request_admission::{RequestAdmissionCounters, RequestAdmissionPolicy};
664mod shutdown;
665
666#[cfg(test)]
667mod access_door_event_tests;
668#[cfg(test)]
669mod access_door_pulse_task_tests;
670#[cfg(test)]
671mod access_zone_event_tests;
672#[cfg(test)]
673mod acknowledge_alarm_tests;
674#[cfg(test)]
675mod active_cov_subscriptions_tests;
676#[cfg(test)]
677mod audit_log_query_tests;
678#[cfg(test)]
679mod averaging_reference_write_tests;
680#[cfg(test)]
681mod averaging_sample_tests;
682#[cfg(test)]
683mod binary_lighting_task_tests;
684#[cfg(test)]
685mod channel_member_concurrency_tests;
686#[cfg(test)]
687mod channel_reliability_tests;
688#[cfg(test)]
689mod channel_remote_datatype_tests;
690#[cfg(test)]
691mod channel_remote_write_tests;
692#[cfg(test)]
693mod channel_run_tests;
694#[cfg(test)]
695mod channel_wire_tests;
696#[cfg(test)]
697mod command_action_run_tests;
698#[cfg(test)]
699mod command_action_wire_tests;
700#[cfg(test)]
701mod command_remote_write_tests;
702#[cfg(test)]
703mod command_run_cancel_tests;
704#[cfg(test)]
705mod command_run_stop_tests;
706#[cfg(test)]
707mod confirmed_broadcast_tests;
708#[cfg(test)]
709mod cov_background_tests;
710#[cfg(test)]
711mod cov_budget_tests;
712#[cfg(test)]
713mod cov_confirmed_baseline_tests;
714#[cfg(test)]
715mod cov_confirmed_context_tests;
716#[cfg(test)]
717mod cov_multiple_admission_tests;
718#[cfg(test)]
719mod cov_notifications_tests;
720#[cfg(test)]
721mod cov_quota_tests;
722#[cfg(test)]
723mod cov_timed_capture_order_tests;
724#[cfg(test)]
725mod cov_timed_chunk_tests;
726#[cfg(test)]
727mod cov_timed_deadline_tests;
728#[cfg(test)]
729mod cov_timed_multiple_tests;
730#[cfg(test)]
731mod cov_timed_producer_tests;
732#[cfg(test)]
733mod cov_timed_value_split_tests;
734#[cfg(test)]
735mod cov_untimed_split_tests;
736#[cfg(test)]
737mod cov_wire_test_support;
738#[cfg(test)]
739mod dcc_event_detection_tests;
740#[cfg(test)]
741mod device_bindings_tests;
742#[cfg(test)]
743mod device_recipient_routing_tests;
744#[cfg(all(test, feature = "sc-tls"))]
745mod direct_principal_tests;
746#[cfg(test)]
747mod discovery_dcc_tests;
748#[cfg(test)]
749mod discovery_tests;
750#[cfg(test)]
751mod event_confirmed_routing_tests;
752#[cfg(test)]
753mod event_enable_distribution_tests;
754#[cfg(test)]
755mod event_enrollment_task_tests;
756#[cfg(test)]
757mod event_forwarding_bounds_tests;
758#[cfg(test)]
759mod event_forwarding_cap_tests;
760#[cfg(test)]
761mod event_forwarding_origin_tests;
762#[cfg(test)]
763mod event_forwarding_rule_tests;
764#[cfg(test)]
765mod event_forwarding_tests;
766#[cfg(test)]
767mod event_log_notification_tests;
768#[cfg(test)]
769mod event_network_priority_tests;
770#[cfg(test)]
771mod event_notifications_tests;
772#[cfg(test)]
773mod event_recipient_routing_tests;
774#[cfg(test)]
775mod life_safety_application_tests;
776#[cfg(test)]
777mod life_safety_cov_tests;
778#[cfg(test)]
779mod life_safety_operation_replay_tests;
780#[cfg(test)]
781mod life_safety_operation_tests;
782#[cfg(test)]
783mod lighting_command_member_tests;
784#[cfg(test)]
785mod lighting_engine_task_tests;
786#[cfg(test)]
787mod lighting_present_value_tests;
788#[cfg(test)]
789mod list_element_event_tests;
790#[cfg(test)]
791mod local_network_number_tests;
792#[cfg(test)]
793mod local_network_outbound_tests;
794#[cfg(test)]
795mod log_reference_resize_tests;
796#[cfg(test)]
797mod loop_controlled_variable_tests;
798#[cfg(test)]
799mod loop_cov_tests;
800#[cfg(test)]
801mod mistagged_request_wire_tests;
802#[cfg(test)]
803mod noncommandable_null_cov_tests;
804#[cfg(test)]
805mod notification_dcc_tests;
806#[cfg(test)]
807mod notification_transactions_tests;
808#[cfg(test)]
809mod pulse_converter_cov_tests;
810#[cfg(test)]
811mod pulse_converter_reference_tests;
812#[cfg(test)]
813mod rb07_provenance_tests;
814#[cfg(test)]
815mod reference_write_wire_tests;
816#[cfg(test)]
817mod remote_write_answer_tests;
818#[cfg(test)]
819mod remote_write_discovery_tests;
820#[cfg(test)]
821mod run_cycle_tests;
822#[cfg(test)]
823mod schedule_create_retry_tests;
824#[cfg(test)]
825mod schedule_reference_list_tests;
826#[cfg(test)]
827mod schedule_reference_write_tests;
828#[cfg(test)]
829mod schedule_write_tests;
830#[cfg(test)]
831mod segmentation_tests;
832#[cfg(test)]
833mod staging_cov_tests;
834#[cfg(test)]
835mod staging_reference_write_tests;
836#[cfg(test)]
837mod subscribed_recipients_expiry_tests;
838#[cfg(test)]
839mod table_13_1_cov_tests;
840#[cfg(test)]
841pub(crate) mod test_forwarder;
842#[cfg(test)]
843pub(crate) mod test_transport;
844#[cfg(test)]
845mod tests;
846#[cfg(test)]
847mod trailing_octet_wire_tests;
848#[cfg(test)]
849mod truncated_request_wire_tests;
850#[cfg(test)]
851mod value_cov_increment_tests;
852
853impl<T: TransportPort + 'static> BACnetServer<T> {
854 pub fn generic_builder() -> ServerBuilder<T> {
857 ServerBuilder {
858 config: ServerConfig::default(),
859 db: ObjectDatabase::new(),
860 transport: None,
861 configured_device_bindings: Vec::new(),
862 }
863 }
864
865 pub fn discovery_counters(&self) -> DiscoveryCounters {
867 self.discovery_limiter.counters()
868 }
869
870 pub fn cov_counters(&self) -> CovCounters {
872 self.cov_counters.snapshot()
873 }
874
875 pub fn mutation_decision_counters(&self) -> crate::mutation::MutationDecisionCounters {
879 self.mutation_decisions.snapshot()
880 }
881
882 pub async fn remove_peer_subscriptions(
886 &self,
887 mac: &[u8],
888 network: Option<&NpduAddress>,
889 ) -> usize {
890 let mut table = self.cov_table.write().await;
891 table.remove_peer_subscriptions(mac, network)
892 }
893}
894
895#[cfg(test)]
896mod cov_identity_completion_tests;
897
898mod broadcaster;