1use super::*;
3
4use bacnet_services::read_range::{
5 RangeSpec, ReadRangeAck, ReadRangeReply, ReadRangeRequest, ReadRangeValidation,
6};
7use bacnet_types::enums::PropertyIdentifier;
8use bacnet_types::primitives::ObjectIdentifier;
9
10use crate::log_reader::{LogCursor, LogPage, LogRequester};
11
12impl<T: TransportPort + 'static> BACnetClient<T> {
13 pub async fn read_range(
21 &self,
22 destination_mac: &[u8],
23 object_identifier: ObjectIdentifier,
24 property_identifier: PropertyIdentifier,
25 property_array_index: Option<u32>,
26 range: Option<RangeSpec>,
27 ) -> Result<ReadRangeAck, Error> {
28 let request = ReadRangeRequest {
29 object_identifier,
30 property_identifier,
31 property_array_index,
32 range,
33 };
34 self.read_range_with(destination_mac, &request, ReadRangeValidation::Strict)
35 .await
36 .map(|reply| reply.ack)
37 }
38
39 pub async fn read_range_with(
47 &self,
48 destination_mac: &[u8],
49 request: &ReadRangeRequest,
50 validation: ReadRangeValidation,
51 ) -> Result<ReadRangeReply, Error> {
52 let mut buf = BytesMut::new();
53 request.encode(&mut buf)?;
54 let response = self
55 .confirmed_request(destination_mac, ConfirmedServiceChoice::READ_RANGE, &buf)
56 .await?;
57 ReadRangeReply::check(request, ReadRangeAck::decode(&response)?, validation)
58 }
59
60 pub async fn read_range_from_device(
65 &self,
66 device_instance: u32,
67 object_identifier: ObjectIdentifier,
68 property_identifier: PropertyIdentifier,
69 property_array_index: Option<u32>,
70 range: Option<RangeSpec>,
71 ) -> Result<ReadRangeAck, Error> {
72 let request = ReadRangeRequest {
73 object_identifier,
74 property_identifier,
75 property_array_index,
76 range,
77 };
78 self.read_range_from_device_with(device_instance, &request, ReadRangeValidation::Strict)
79 .await
80 .map(|reply| reply.ack)
81 }
82
83 pub async fn read_range_from_device_with(
88 &self,
89 device_instance: u32,
90 request: &ReadRangeRequest,
91 validation: ReadRangeValidation,
92 ) -> Result<ReadRangeReply, Error> {
93 let (mac, routing) = self.resolve_device(device_instance).await?;
94 if let Some((network, address)) = routing {
95 self.read_range_routed(&mac, network, &address, request, validation)
96 .await
97 } else {
98 self.read_range_with(&mac, request, validation).await
99 }
100 }
101
102 pub async fn read_log_page_from_device(
109 &self,
110 device_instance: u32,
111 log: ObjectIdentifier,
112 cursor: LogCursor,
113 page_size: u16,
114 ) -> Result<LogPage, Error> {
115 let (mac, routing) = self.resolve_device(device_instance).await?;
116 if let Some((network, address)) = routing {
117 let requester = RoutedLogRequester {
118 client: self,
119 network,
120 address: &address,
121 };
122 crate::log_reader::read_log_page(&requester, &mac, log, cursor, page_size).await
123 } else {
124 self.read_log_page(&mac, log, cursor, page_size).await
125 }
126 }
127
128 async fn read_range_routed(
130 &self,
131 router_mac: &[u8],
132 network: u16,
133 address: &[u8],
134 request: &ReadRangeRequest,
135 validation: ReadRangeValidation,
136 ) -> Result<ReadRangeReply, Error> {
137 let mut buf = BytesMut::new();
138 request.encode(&mut buf)?;
139 let response = self
140 .confirmed_request_routed(
141 router_mac,
142 network,
143 address,
144 ConfirmedServiceChoice::READ_RANGE,
145 &buf,
146 )
147 .await?;
148 ReadRangeReply::check(request, ReadRangeAck::decode(&response)?, validation)
149 }
150}
151
152struct RoutedLogRequester<'a, T: TransportPort> {
154 client: &'a BACnetClient<T>,
155 network: u16,
156 address: &'a [u8],
157}
158
159impl<T: TransportPort + 'static> LogRequester for RoutedLogRequester<'_, T> {
160 async fn read_unsigned(
161 &self,
162 router_mac: &[u8],
163 log: ObjectIdentifier,
164 property: PropertyIdentifier,
165 ) -> Result<u64, Error> {
166 let ack = self
167 .client
168 .read_property_routed(router_mac, self.network, self.address, log, property, None)
169 .await?;
170 crate::log_reader::unsigned_value(&ack.property_value)
171 }
172
173 async fn read_range_lenient(
174 &self,
175 router_mac: &[u8],
176 request: &ReadRangeRequest,
177 ) -> Result<ReadRangeReply, Error> {
178 self.client
179 .read_range_routed(
180 router_mac,
181 self.network,
182 self.address,
183 request,
184 ReadRangeValidation::Lenient,
185 )
186 .await
187 }
188}
189
190#[cfg(test)]
191#[path = "routed_read_services_tests.rs"]
192mod tests;