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::{BipMode, 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::life_safety::{LifeSafetyOperationAuthorizationContext, LifeSafetyOperationAuthorizer};
64use crate::{handlers, runtime_clock};
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 MAX_NEG_SEGMENT_ACK_RETRIES: u8 = 3;
105
106const DEFAULT_APDU_SEGMENT_TIMEOUT: Duration = Duration::from_secs(5);
108
109const DEFAULT_APDU_SEGMENT_RETRIES: u8 = MAX_NEG_SEGMENT_ACK_RETRIES;
111
112const DEFAULT_APDU_RETRIES: u8 = 3;
115
116#[derive(Debug, Clone)]
118pub struct TimeSyncData {
119 pub raw_service_data: Bytes,
121 pub is_utc: bool,
123 pub source_mac: MacAddr,
126 pub source_network: Option<NpduAddress>,
128 pub provenance: bacnet_transport::port::TransportProvenance,
131}
132
133mod config;
134pub use config::ServerConfig;
135mod audit_batch_queue;
136mod audit_batch_runtime;
137mod audit_context_preparation;
138mod audit_forwarder;
139#[cfg(test)]
140mod audit_forwarder_tests;
141mod audit_recipient;
142mod audit_recipient_routes;
143mod audit_reporter;
144mod audit_reporter_changes;
145mod audit_send_now;
146mod heap_futures;
147pub use audit_reporter::{valid_bip_audit_address, AuditReportersConfig};
148#[cfg(test)]
149mod audit_reporter_tests;
150
151pub struct ServerBuilder<T: TransportPort> {
153 config: ServerConfig,
154 db: ObjectDatabase,
155 transport: Option<T>,
156 configured_device_bindings: Vec<DeviceBinding>,
157}
158
159impl<T: TransportPort + 'static> ServerBuilder<T> {
160 pub fn database(mut self, db: ObjectDatabase) -> Self {
162 self.db = db;
163 self
164 }
165
166 pub fn transport(mut self, transport: T) -> Self {
168 self.transport = Some(transport);
169 self
170 }
171
172 pub fn device_binding(mut self, binding: DeviceBinding) -> Result<Self, Error> {
174 register_configured_binding(&mut self.configured_device_bindings, binding)?;
175 Ok(self)
176 }
177
178 pub fn life_safety_operation_authorizer<F>(mut self, authorizer: F) -> Self
180 where
181 F: Fn(&LifeSafetyOperationAuthorizationContext) -> bool + Send + Sync + 'static,
182 {
183 self.config.life_safety_operation_authorizer = Some(Arc::new(authorizer));
184 self
185 }
186
187 pub fn audit_notification_sink(mut self, sink: ObjectIdentifier) -> Self {
189 self.config.audit_notification_sink = Some(sink);
190 self
191 }
192
193 pub fn audit_notification_authorizer<F>(mut self, authorizer: F) -> Self
195 where
196 F: Fn(&AuditNotificationAuthorizationContext) -> bool + Send + Sync + 'static,
197 {
198 self.config.audit_notification_authorizer = Some(Arc::new(authorizer));
199 self
200 }
201
202 pub fn unconfirmed_audit_notification_authorizer<F>(mut self, authorizer: F) -> Self
204 where
205 F: Fn(&UnconfirmedAuditNotificationAuthorizationContext) -> bool + Send + Sync + 'static,
206 {
207 self.config.unconfirmed_audit_notification_authorizer = Some(Arc::new(authorizer));
208 self
209 }
210
211 pub fn enable_fault_detection(mut self, enabled: bool) -> Self {
219 self.config.enable_fault_detection = enabled;
220 self
221 }
222
223 pub fn enable_event_enrollment(mut self, enabled: bool) -> Self {
225 self.config.enable_event_enrollment = enabled;
226 self
227 }
228
229 pub fn event_enrollment_interval_secs(mut self, secs: u64) -> Self {
232 self.config.event_enrollment_interval_secs = secs;
233 self
234 }
235
236 pub fn segmentation_supported(mut self, segmentation: Segmentation) -> Self {
243 self.config.segmentation_supported = segmentation;
244 self
245 }
246
247 pub fn vendor_id(mut self, id: u16) -> Self {
249 self.config.vendor_id = id;
250 self
251 }
252
253 pub fn discovery_policy(mut self, policy: DiscoveryPolicy) -> Self {
255 self.config.discovery_policy = policy;
256 self
257 }
258
259 pub fn cov_policy(mut self, policy: CovPolicy) -> Self {
262 self.config.cov_policy = policy;
263 self
264 }
265
266 pub async fn build(self) -> Result<BACnetServer<T>, Error> {
268 let transport = self
269 .transport
270 .ok_or_else(|| Error::Encoding("transport not set on ServerBuilder".into()))?;
271 BACnetServer::start_with_clock_mode_and_bindings(
272 self.config,
273 self.db,
274 transport,
275 Some(ClockConfig::default()),
276 self.configured_device_bindings,
277 )
278 .await
279 }
280}
281
282pub struct BipServerBuilder {
284 config: ServerConfig,
285 db: ObjectDatabase,
286 configured_device_bindings: Vec<DeviceBinding>,
287 mode: BipMode,
288}
289
290impl BipServerBuilder {
291 pub fn interface(mut self, ip: Ipv4Addr) -> Self {
293 self.config.interface = ip;
294 self
295 }
296
297 pub fn port(mut self, port: u16) -> Self {
299 self.config.port = port;
300 self
301 }
302
303 pub fn broadcast_address(mut self, addr: Ipv4Addr) -> Self {
305 self.config.broadcast_address = addr;
306 self
307 }
308
309 pub fn database(mut self, db: ObjectDatabase) -> Self {
311 self.db = db;
312 self
313 }
314
315 pub fn device_binding(mut self, binding: DeviceBinding) -> Result<Self, Error> {
317 register_configured_binding(&mut self.configured_device_bindings, binding)?;
318 Ok(self)
319 }
320
321 pub fn life_safety_operation_authorizer<F>(mut self, authorizer: F) -> Self
323 where
324 F: Fn(&LifeSafetyOperationAuthorizationContext) -> bool + Send + Sync + 'static,
325 {
326 self.config.life_safety_operation_authorizer = Some(Arc::new(authorizer));
327 self
328 }
329
330 pub fn audit_notification_sink(mut self, sink: ObjectIdentifier) -> Self {
332 self.config.audit_notification_sink = Some(sink);
333 self
334 }
335
336 pub fn audit_notification_authorizer<F>(mut self, authorizer: F) -> Self
338 where
339 F: Fn(&AuditNotificationAuthorizationContext) -> bool + Send + Sync + 'static,
340 {
341 self.config.audit_notification_authorizer = Some(Arc::new(authorizer));
342 self
343 }
344
345 pub fn unconfirmed_audit_notification_authorizer<F>(mut self, authorizer: F) -> Self
347 where
348 F: Fn(&UnconfirmedAuditNotificationAuthorizationContext) -> bool + Send + Sync + 'static,
349 {
350 self.config.unconfirmed_audit_notification_authorizer = Some(Arc::new(authorizer));
351 self
352 }
353
354 pub fn enable_fault_detection(mut self, enabled: bool) -> Self {
362 self.config.enable_fault_detection = enabled;
363 self
364 }
365
366 pub fn enable_event_enrollment(mut self, enabled: bool) -> Self {
368 self.config.enable_event_enrollment = enabled;
369 self
370 }
371
372 pub fn event_enrollment_interval_secs(mut self, secs: u64) -> Self {
375 self.config.event_enrollment_interval_secs = secs;
376 self
377 }
378
379 pub fn segmentation_supported(mut self, segmentation: Segmentation) -> Self {
386 self.config.segmentation_supported = segmentation;
387 self
388 }
389
390 pub fn vendor_id(mut self, id: u16) -> Self {
392 self.config.vendor_id = id;
393 self
394 }
395
396 pub fn discovery_policy(mut self, policy: DiscoveryPolicy) -> Self {
398 self.config.discovery_policy = policy;
399 self
400 }
401
402 pub fn cov_policy(mut self, policy: CovPolicy) -> Self {
405 self.config.cov_policy = policy;
406 self
407 }
408
409 pub async fn build(self) -> Result<BACnetServer<BipTransport>, Error> {
411 let config = &self.config;
412 let mut transport =
413 BipTransport::new(config.interface, config.port, config.broadcast_address);
414 transport.set_share_port_by_address(config.share_port_by_address);
415 transport.set_mode(self.mode);
416 BACnetServer::start_with_clock_mode_and_bindings(
417 self.config,
418 self.db,
419 transport,
420 Some(ClockConfig::default()),
421 self.configured_device_bindings,
422 )
423 .await
424 }
425}
426
427type TransportCleanup<T> = JoinHandle<(NetworkLayer<T>, Result<(), Error>)>;
428
429pub struct BACnetServer<T: TransportPort> {
431 target_audit: Option<Arc<audit_recipient::TargetAudit<T>>>,
432 config: Arc<ServerConfig>,
434 discovery_limiter: Arc<DiscoveryLimiter>,
435 #[allow(dead_code)] time_sync_limiter: Arc<TimeSyncLimiter>,
437 _clock: Option<Arc<ServerClock>>,
439 network: Option<Arc<NetworkLayer<T>>>,
442 broadcaster: Arc<broadcaster::BroadcasterState<T>>,
443 transport_cleanup: Option<TransportCleanup<T>>,
444 transport_cleanup_error: Option<String>,
445 network_number_task: Option<JoinHandle<()>>,
446 db: Arc<RwLock<ObjectDatabase>>,
448 cov_table: Arc<RwLock<CovSubscriptionTable>>,
451 cov_counters: Arc<crate::cov::AtomicCovCounters>,
452 #[allow(dead_code)]
454 seg_ack_senders: Arc<segmented_send::SegmentedSendRegistry>,
455 #[allow(dead_code)]
458 seg_send_permits: Arc<Semaphore>,
459 cov_in_flight: Arc<Semaphore>,
462 learned_routers: Arc<Mutex<LearnedRouterCache>>,
464 notification_transactions: Arc<NotificationTransactions>,
466 confirmed_request_tracker: Arc<ConfirmedRequestTracker>,
468 device_bindings: Arc<RwLock<DeviceBindingTable>>,
470 comm_state: Arc<CommState>,
472 dcc_timer: Arc<Mutex<crate::server::dcc_timer::TimerSlot>>,
475 dcc_outcomes: Arc<dcc_outcomes::DccOutcomes>,
476 event_suppressions: Arc<event_suppression::EventSuppressions>,
478 mutation_decisions: Arc<crate::mutation::MutationDecisions>,
479 dispatch_task: Option<JoinHandle<()>>,
480 request_tasks: Arc<request_tasks::RequestTasks>,
481 cov_purge_task: Option<JoinHandle<()>>,
482 fault_detection_task: Option<JoinHandle<()>>,
483 event_enrollment_task: Option<JoinHandle<()>>,
484 trend_log_task: Option<JoinHandle<()>>,
485 schedule_tick_task: Option<JoinHandle<()>>,
486 intrinsic_reporting_task: Option<JoinHandle<()>>,
488 binary_lighting_operation_task: Option<JoinHandle<()>>,
491 cov_revisit_task: Option<JoinHandle<()>>,
493 local_mac: MacAddr,
494}
495
496pub struct IAmBroadcaster<T: TransportPort> {
503 state: std::sync::Weak<broadcaster::BroadcasterState<T>>,
504}
505
506impl<T: TransportPort> Clone for IAmBroadcaster<T> {
507 fn clone(&self) -> Self {
508 Self {
509 state: self.state.clone(),
510 }
511 }
512}
513
514impl BACnetServer<BipTransport> {
515 pub fn bip_builder() -> BipServerBuilder {
517 BipServerBuilder {
518 config: ServerConfig::default(),
519 db: ObjectDatabase::new(),
520 configured_device_bindings: Vec::new(),
521 mode: BipMode::Normal,
522 }
523 }
524}
525
526mod clock;
527mod command_runs;
528mod reinitialize;
529mod time_sync_policy;
530pub use reinitialize::{ReinitializeContext, ReinitializeHandler};
531mod write_group;
532#[cfg(test)]
533pub(crate) use clock::clocked_test_database;
534pub use clock::ClockConfig;
535use clock::ServerClock;
536use time_sync_policy::{request_limiters, TimeSyncLimiter};
537pub use time_sync_policy::{
538 TimeSyncPolicy, TimeSyncRateLimit, TimeSyncSource, TimeSyncSourceRestriction,
539};
540mod binary_lighting_lifecycle;
541#[cfg(test)]
542mod confirmed_issuance_tests;
543mod confirmed_request_tracker;
544mod cov_clock;
545mod cov_encoding;
546mod cov_fanout;
547mod cov_notifications;
548mod cov_notify_context;
549mod cov_snapshot;
550mod dcc_disable_rate;
551pub(crate) mod dcc_outcomes;
552mod dcc_policy;
553mod lso_replay;
554pub use dcc_disable_rate::DccDisableRateLimit;
555mod dcc_timer;
556pub use dcc_outcomes::DccOutcomeCounters;
557pub use dcc_policy::{DccPolicy, DccSource, DccSourceRestriction};
558use dcc_timer::CommState;
559pub use dcc_timer::DccState;
560mod binding_probes;
561mod device_bindings;
562mod discovery;
563#[doc(hidden)]
564pub use discovery::iam_request_for as discovery_iam_for_test;
565pub use discovery::{DiscoveryCounters, DiscoveryPolicy};
566pub(crate) use discovery::{DiscoveryLimiter, PreCheckDecision, WhoHasTarget};
567mod audit_log_purge;
568mod dispatch;
569mod durable_writes;
570#[doc(hidden)]
571pub use durable_writes::settle_endpoint as __endpoint_settle_durable_writes;
572mod event_delivery;
573mod event_enrollment_lifecycle;
574mod event_forwarding;
575pub use event_forwarding::MAX_FORWARDED_DESTINATIONS;
576mod event_forwarding_repeats;
577mod event_message_policy;
578pub(crate) mod event_notification_payload;
579mod event_notifications;
580mod event_recipient_route;
581mod event_send;
582mod event_suppression;
583pub use event_suppression::EventNotificationCounters;
584mod received_event_log;
585pub use received_event_log::{RECEIVED_EVENT_LOG_RATE, RECEIVED_EVENT_LOG_SOURCES};
586mod confirmed_answer;
587pub(crate) mod event_timestamp;
588mod handles;
589mod learned_router_cache;
590mod lifecycle;
591mod local_writes;
592mod network_port;
593#[cfg(test)]
594mod network_port_tests;
595pub use confirmed_answer::{CovAckResult, Refusal};
596mod remote_writes;
597pub(crate) use remote_writes::RemoteRequestError;
598mod notification_transactions;
599#[doc(hidden)]
600pub use notification_transactions::{
601 canonical_direct_peer as __endpoint_canonical_direct_peer,
602 canonical_routed_peer as __endpoint_canonical_routed_peer,
603 run_notification_worker as __endpoint_run_notification_worker,
604 AuditFailureContext as __endpoint_AuditFailureContext,
605 AuditFailureQueue as __endpoint_AuditFailureQueue,
606 AuditFailureTicket as __endpoint_AuditFailureTicket,
607 NotificationOperation as __endpoint_NotificationOperation,
608 NotificationReserveError as __endpoint_NotificationReserveError,
609 NotificationTransactions as __endpoint_NotificationTransactions,
610 NotificationWorkerResult as __endpoint_NotificationWorkerResult,
611};
612mod requests;
613#[doc(hidden)]
614pub use requests::endpoint_responder::EndpointResponder as __endpoint_EndpointResponder;
615#[cfg(feature = "sc-tls")]
616mod sc_builder;
617#[cfg(test)]
618pub(crate) use requests::{EXECUTED_CONFIRMED, EXECUTED_UNCONFIRMED};
619#[cfg(test)]
620mod audit_notification_tests;
621#[cfg(test)]
622mod unconfirmed_audit_notification_tests;
623#[cfg(feature = "sc-tls")]
624pub use sc_builder::ScServerBuilder;
625mod responses;
626mod segmentation;
627mod segmented_receive;
628mod segmented_send;
629pub(crate) use segmented_send::*;
630mod request_admission;
631mod rpm_budget;
632pub use rpm_budget::ReadPropertyMultipleBudget;
633mod alarm_summary_budget;
634pub use alarm_summary_budget::GetAlarmSummaryBudget;
635mod atomic_read_file_budget;
636mod atomic_write_file_budget;
637mod read_range_budget;
638pub use read_range_budget::ReadRangeBudget;
639mod event_information_budget;
640pub use event_information_budget::GetEventInformationBudget;
641mod enrollment_summary_budget;
642pub use atomic_read_file_budget::AtomicReadFileBudget;
643pub use atomic_write_file_budget::AtomicWriteFileBudget;
644pub use enrollment_summary_budget::GetEnrollmentSummaryBudget;
645#[cfg(test)]
646mod atomic_read_file_tests;
647#[cfg(test)]
648mod atomic_write_file_tests;
649#[cfg(test)]
650mod enrollment_summary_tests;
651mod request_peer;
652mod request_services;
653mod request_tasks;
654pub use request_admission::{RequestAdmissionCounters, RequestAdmissionPolicy};
655mod shutdown;
656pub use shutdown::drop_database_off_runtime;
657
658#[cfg(test)]
659mod access_door_event_tests;
660#[cfg(test)]
661mod access_door_pulse_task_tests;
662#[cfg(test)]
663mod access_zone_event_tests;
664#[cfg(test)]
665mod acknowledge_alarm_tests;
666#[cfg(test)]
667mod active_cov_subscriptions_tests;
668#[cfg(test)]
669mod audit_log_query_tests;
670#[cfg(test)]
671mod averaging_reference_write_tests;
672#[cfg(test)]
673mod averaging_sample_tests;
674#[cfg(test)]
675mod binary_lighting_task_tests;
676#[cfg(test)]
677mod channel_member_concurrency_tests;
678#[cfg(test)]
679mod channel_reliability_tests;
680#[cfg(test)]
681mod channel_remote_datatype_tests;
682#[cfg(test)]
683mod channel_remote_write_tests;
684#[cfg(test)]
685mod channel_run_tests;
686#[cfg(test)]
687mod channel_wire_tests;
688#[cfg(test)]
689mod color_channel_member_tests;
690#[cfg(test)]
691mod color_engine_task_tests;
692#[cfg(test)]
693mod command_action_run_tests;
694#[cfg(test)]
695mod command_action_wire_tests;
696#[cfg(test)]
697mod command_remote_write_tests;
698#[cfg(test)]
699mod command_run_cancel_tests;
700#[cfg(test)]
701mod command_run_stop_tests;
702#[cfg(test)]
703mod confirmed_broadcast_tests;
704#[cfg(test)]
705mod cov_background_tests;
706#[cfg(test)]
707mod cov_budget_tests;
708#[cfg(test)]
709mod cov_confirmed_baseline_tests;
710#[cfg(test)]
711mod cov_confirmed_context_tests;
712#[cfg(test)]
713mod cov_multiple_admission_tests;
714#[cfg(test)]
715mod cov_notifications_tests;
716#[cfg(test)]
717mod cov_quota_tests;
718#[cfg(test)]
719mod cov_timed_capture_order_tests;
720#[cfg(test)]
721mod cov_timed_chunk_tests;
722#[cfg(test)]
723mod cov_timed_deadline_tests;
724#[cfg(test)]
725mod cov_timed_multiple_tests;
726#[cfg(test)]
727mod cov_timed_producer_tests;
728#[cfg(test)]
729mod cov_timed_value_split_tests;
730#[cfg(test)]
731mod cov_untimed_split_tests;
732#[cfg(test)]
733mod cov_wire_test_support;
734#[cfg(test)]
735mod dcc_event_detection_tests;
736#[cfg(test)]
737mod device_bindings_tests;
738#[cfg(test)]
739mod device_recipient_routing_tests;
740#[cfg(all(test, feature = "sc-tls"))]
741mod direct_principal_tests;
742#[cfg(test)]
743mod discovery_dcc_tests;
744#[cfg(test)]
745mod discovery_tests;
746#[cfg(test)]
747mod event_confirmed_routing_tests;
748#[cfg(test)]
749mod event_enable_distribution_tests;
750#[cfg(test)]
751mod event_enrollment_task_tests;
752#[cfg(test)]
753mod event_forwarding_bounds_tests;
754#[cfg(test)]
755mod event_forwarding_cap_tests;
756#[cfg(test)]
757mod event_forwarding_origin_tests;
758#[cfg(test)]
759mod event_forwarding_rule_tests;
760#[cfg(test)]
761mod event_forwarding_tests;
762#[cfg(test)]
763mod event_log_notification_tests;
764#[cfg(test)]
765mod event_network_priority_tests;
766#[cfg(test)]
767mod event_notifications_tests;
768#[cfg(test)]
769mod event_recipient_routing_tests;
770#[cfg(test)]
771mod life_safety_application_tests;
772#[cfg(test)]
773mod life_safety_cov_tests;
774#[cfg(test)]
775mod life_safety_operation_replay_tests;
776#[cfg(test)]
777mod life_safety_operation_tests;
778#[cfg(test)]
779mod lighting_command_member_tests;
780#[cfg(test)]
781mod lighting_engine_task_tests;
782#[cfg(test)]
783mod lighting_present_value_tests;
784#[cfg(test)]
785mod list_element_event_tests;
786#[cfg(test)]
787mod local_network_number_tests;
788#[cfg(test)]
789mod local_network_outbound_tests;
790#[cfg(test)]
791mod log_reference_resize_tests;
792#[cfg(test)]
793mod loop_controlled_variable_tests;
794#[cfg(test)]
795mod loop_cov_tests;
796#[cfg(test)]
797mod mistagged_request_wire_tests;
798#[cfg(test)]
799mod noncommandable_null_cov_tests;
800#[cfg(test)]
801mod notification_dcc_tests;
802#[cfg(test)]
803mod notification_transactions_tests;
804#[cfg(test)]
805mod pulse_converter_cov_tests;
806#[cfg(test)]
807mod pulse_converter_reference_tests;
808#[cfg(test)]
809mod rb07_provenance_tests;
810#[cfg(test)]
811mod reference_write_wire_tests;
812#[cfg(test)]
813mod remote_write_answer_tests;
814#[cfg(test)]
815mod remote_write_discovery_tests;
816#[cfg(test)]
817mod run_cycle_tests;
818#[cfg(test)]
819mod schedule_create_retry_tests;
820#[cfg(test)]
821mod schedule_reference_list_tests;
822#[cfg(test)]
823mod schedule_reference_write_tests;
824#[cfg(test)]
825mod schedule_write_tests;
826#[cfg(test)]
827mod segmentation_tests;
828#[cfg(test)]
829mod staging_cov_tests;
830#[cfg(test)]
831mod staging_reference_write_tests;
832#[cfg(test)]
833mod subscribed_recipients_expiry_tests;
834#[cfg(test)]
835mod table_13_1_cov_tests;
836#[cfg(test)]
837pub(crate) mod test_forwarder;
838#[cfg(test)]
839pub(crate) mod test_transport;
840#[cfg(test)]
841mod tests;
842#[cfg(test)]
843mod trailing_octet_wire_tests;
844#[cfg(test)]
845mod truncated_request_wire_tests;
846#[cfg(test)]
847mod value_cov_increment_tests;
848#[cfg(test)]
849mod value_source_local_tests;
850
851impl<T: TransportPort + 'static> BACnetServer<T> {
852 pub fn generic_builder() -> ServerBuilder<T> {
855 ServerBuilder {
856 config: ServerConfig::default(),
857 db: ObjectDatabase::new(),
858 transport: None,
859 configured_device_bindings: Vec::new(),
860 }
861 }
862
863 pub fn discovery_counters(&self) -> DiscoveryCounters {
865 self.discovery_limiter.counters()
866 }
867
868 pub fn cov_counters(&self) -> CovCounters {
870 self.cov_counters.snapshot()
871 }
872
873 pub fn mutation_decision_counters(&self) -> crate::mutation::MutationDecisionCounters {
877 self.mutation_decisions.snapshot()
878 }
879
880 pub async fn remove_peer_subscriptions(
884 &self,
885 mac: &[u8],
886 network: Option<&NpduAddress>,
887 ) -> usize {
888 let mut table = self.cov_table.write().await;
889 table.remove_peer_subscriptions(mac, network)
890 }
891}
892
893#[cfg(test)]
894mod cov_identity_completion_tests;
895
896mod broadcaster;