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;