Skip to main content

bacnet_client/client/
write_group.rs

1//! Sending WriteGroup requests (Clause 15.11).
2//!
3//! WriteGroup is unconfirmed, so it can go to one device or to many at once:
4//! the local network, one remote network through its routers, or every
5//! network. Each receiving device that has Channels in the request's control
6//! group applies the change list to them itself; nothing comes back.
7use super::*;
8use bacnet_services::write_group::WriteGroupRequest;
9
10/// Where [`BACnetClient::write_group`] sends a request.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum WriteGroupDestination {
13    /// One device, by its address on the local network.
14    Device(MacAddr),
15    /// Every device on the local network.
16    LocalBroadcast,
17    /// Every device on one remote network (1 to 65534), through its router.
18    RemoteBroadcast(u16),
19    /// Every device on every network (DNET 65535).
20    GlobalBroadcast,
21}
22
23impl<T: TransportPort + 'static> BACnetClient<T> {
24    /// Send a WriteGroup request to `destination`.
25    ///
26    /// The service is unconfirmed: this returns once the request is sent, and
27    /// no device answers it, so delivery isn't confirmed either. Fails before
28    /// anything is sent when `request` doesn't encode (see
29    /// [`WriteGroupRequest::encode`]) or a remote network number is 0 or
30    /// 65535; use [`WriteGroupDestination::GlobalBroadcast`] for every
31    /// network.
32    pub async fn write_group(
33        &self,
34        destination: &WriteGroupDestination,
35        request: &WriteGroupRequest,
36    ) -> Result<(), Error> {
37        if let WriteGroupDestination::RemoteBroadcast(network) = destination
38            && !(1..u16::MAX).contains(network)
39        {
40            return Err(Error::Encoding(format!(
41                "WriteGroup remote network {network} out of range 1-65534"
42            )));
43        }
44        let mut service = BytesMut::new();
45        request.encode(&mut service)?;
46        let choice = UnconfirmedServiceChoice::WRITE_GROUP;
47        match destination {
48            WriteGroupDestination::Device(mac) => {
49                self.unconfirmed_request(mac, choice, &service).await
50            }
51            WriteGroupDestination::LocalBroadcast => {
52                self.broadcast_unconfirmed(choice, &service).await
53            }
54            WriteGroupDestination::RemoteBroadcast(network) => {
55                self.broadcast_network_unconfirmed(choice, &service, *network)
56                    .await
57            }
58            WriteGroupDestination::GlobalBroadcast => {
59                self.broadcast_global_unconfirmed(choice, &service).await
60            }
61        }
62    }
63}
64
65#[cfg(test)]
66#[path = "write_group_tests.rs"]
67mod tests;