Skip to main content

bacnet_client/client/
cov_notifications.rs

1use super::*;
2use std::fmt;
3
4/// Delivery mode used for a received COV notification.
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum COVNotificationDelivery {
7    /// Notification arrived as a ConfirmedCOVNotification request.
8    Confirmed,
9    /// Notification arrived as an UnconfirmedCOVNotification request.
10    Unconfirmed,
11}
12
13/// Application response policy for a decoded ConfirmedCOVNotification.
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum ConfirmedCOVNotificationResponse {
16    /// Send the standard SimpleAck response.
17    Ack,
18    /// Send a Reject PDU with the supplied reason.
19    Reject(RejectReason),
20    /// Do not respond; the remote sender will time out or retry.
21    NoResponse,
22}
23
24/// Callback used to choose a ConfirmedCOVNotification response after decode.
25pub type ConfirmedCOVNotificationAckPolicy =
26    Arc<dyn Fn(&ReceivedCOVNotification) -> ConfirmedCOVNotificationResponse + Send + Sync>;
27
28/// A decoded inbound COV notification plus transport-observed metadata.
29#[derive(Debug, Clone, PartialEq)]
30pub struct ReceivedCOVNotification {
31    /// Decoded COV notification service payload.
32    pub notification: COVNotificationRequest,
33    /// Immediate transport source MAC that delivered the NPDU.
34    pub source_mac: MacAddr,
35    /// NPDU source network, when supplied by a routed sender.
36    pub source_network: Option<u16>,
37    /// NPDU source MAC/address, when supplied by a routed sender.
38    pub source_address: Option<MacAddr>,
39    /// Whether the notification arrived through the confirmed or unconfirmed service.
40    pub delivery: COVNotificationDelivery,
41}
42
43impl ReceivedCOVNotification {
44    pub(crate) fn new(
45        notification: COVNotificationRequest,
46        source_mac: &[u8],
47        source_network: &Option<NpduAddress>,
48        delivery: COVNotificationDelivery,
49    ) -> Self {
50        let (network, address) = match source_network {
51            Some(npdu_addr) if !npdu_addr.mac_address.is_empty() => {
52                (Some(npdu_addr.network), Some(npdu_addr.mac_address.clone()))
53            }
54            _ => (None, None),
55        };
56
57        Self {
58            notification,
59            source_mac: MacAddr::from_slice(source_mac),
60            source_network: network,
61            source_address: address,
62            delivery,
63        }
64    }
65}
66
67pub(crate) fn default_confirmed_cov_notification_ack_policy() -> ConfirmedCOVNotificationAckPolicy {
68    Arc::new(|_| ConfirmedCOVNotificationResponse::Ack)
69}
70
71impl ClientOptions {
72    /// Set a callback that chooses how to answer decoded ConfirmedCOVNotifications.
73    pub fn with_confirmed_cov_notification_ack_policy<F>(mut self, policy: F) -> Self
74    where
75        F: Fn(&ReceivedCOVNotification) -> ConfirmedCOVNotificationResponse + Send + Sync + 'static,
76    {
77        self.confirmed_cov_notification_ack_policy = Arc::new(policy);
78        self
79    }
80}
81
82impl fmt::Debug for ClientOptions {
83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84        f.debug_struct("ClientOptions")
85            .field("cov_channel_capacity", &self.cov_channel_capacity)
86            .field("confirmed_cov_notification_ack_policy", &"<callback>")
87            .finish()
88    }
89}