1use super::*;
2
3impl<T: TransportPort + 'static> BACnetClient<T> {
4 pub async fn read_property(
6 &self,
7 destination_mac: &[u8],
8 object_identifier: bacnet_types::primitives::ObjectIdentifier,
9 property_identifier: bacnet_types::enums::PropertyIdentifier,
10 property_array_index: Option<u32>,
11 ) -> Result<bacnet_services::read_property::ReadPropertyACK, Error> {
12 use bacnet_services::read_property::ReadPropertyRequest;
13
14 let request = ReadPropertyRequest {
15 object_identifier,
16 property_identifier,
17 property_array_index,
18 };
19 let mut buf = BytesMut::new();
20 request.encode(&mut buf);
21
22 let response_data = self
23 .confirmed_request(destination_mac, ConfirmedServiceChoice::READ_PROPERTY, &buf)
24 .await?;
25
26 bacnet_services::read_property::ReadPropertyACK::decode(&response_data)
27 }
28
29 pub async fn read_property_from_device(
31 &self,
32 device_instance: u32,
33 object_identifier: bacnet_types::primitives::ObjectIdentifier,
34 property_identifier: bacnet_types::enums::PropertyIdentifier,
35 property_array_index: Option<u32>,
36 ) -> Result<bacnet_services::read_property::ReadPropertyACK, Error> {
37 let (mac, routing) = {
38 let dt = self.device_table.lock().await;
39 let device = dt.get(device_instance).ok_or_else(|| {
40 Error::Encoding(format!("device {device_instance} not in device table"))
41 })?;
42 let routing = match (&device.source_network, &device.source_address) {
43 (Some(snet), Some(sadr)) => Some((*snet, sadr.to_vec())),
44 _ => None,
45 };
46 (device.mac_address.to_vec(), routing)
47 };
48
49 if let Some((dnet, dadr)) = routing {
50 self.read_property_routed(
51 &mac,
52 dnet,
53 &dadr,
54 object_identifier,
55 property_identifier,
56 property_array_index,
57 )
58 .await
59 } else {
60 self.read_property(
61 &mac,
62 object_identifier,
63 property_identifier,
64 property_array_index,
65 )
66 .await
67 }
68 }
69
70 pub async fn read_property_routed(
72 &self,
73 router_mac: &[u8],
74 dest_network: u16,
75 dest_mac: &[u8],
76 object_identifier: bacnet_types::primitives::ObjectIdentifier,
77 property_identifier: bacnet_types::enums::PropertyIdentifier,
78 property_array_index: Option<u32>,
79 ) -> Result<bacnet_services::read_property::ReadPropertyACK, Error> {
80 use bacnet_services::read_property::ReadPropertyRequest;
81
82 let request = ReadPropertyRequest {
83 object_identifier,
84 property_identifier,
85 property_array_index,
86 };
87 let mut buf = BytesMut::new();
88 request.encode(&mut buf);
89
90 let response_data = self
91 .confirmed_request_routed(
92 router_mac,
93 dest_network,
94 dest_mac,
95 ConfirmedServiceChoice::READ_PROPERTY,
96 &buf,
97 )
98 .await?;
99
100 bacnet_services::read_property::ReadPropertyACK::decode(&response_data)
101 }
102
103 pub async fn read_property_multiple(
105 &self,
106 destination_mac: &[u8],
107 specs: Vec<bacnet_services::rpm::ReadAccessSpecification>,
108 ) -> Result<bacnet_services::rpm::ReadPropertyMultipleACK, Error> {
109 use bacnet_services::rpm::{ReadPropertyMultipleACK, ReadPropertyMultipleRequest};
110
111 let request = ReadPropertyMultipleRequest {
112 list_of_read_access_specs: specs,
113 };
114 let mut buf = BytesMut::new();
115 request.encode(&mut buf);
116
117 let response_data = self
118 .confirmed_request(
119 destination_mac,
120 ConfirmedServiceChoice::READ_PROPERTY_MULTIPLE,
121 &buf,
122 )
123 .await?;
124
125 ReadPropertyMultipleACK::decode(&response_data)
126 }
127
128 pub async fn read_property_multiple_from_device(
130 &self,
131 device_instance: u32,
132 specs: Vec<bacnet_services::rpm::ReadAccessSpecification>,
133 ) -> Result<bacnet_services::rpm::ReadPropertyMultipleACK, Error> {
134 let (mac, routing) = self.resolve_device(device_instance).await?;
135
136 if let Some((dnet, dadr)) = routing {
137 use bacnet_services::rpm::{ReadPropertyMultipleACK, ReadPropertyMultipleRequest};
138
139 let request = ReadPropertyMultipleRequest {
140 list_of_read_access_specs: specs,
141 };
142 let mut buf = BytesMut::new();
143 request.encode(&mut buf);
144
145 let response_data = self
146 .confirmed_request_routed(
147 &mac,
148 dnet,
149 &dadr,
150 ConfirmedServiceChoice::READ_PROPERTY_MULTIPLE,
151 &buf,
152 )
153 .await?;
154
155 ReadPropertyMultipleACK::decode(&response_data)
156 } else {
157 self.read_property_multiple(&mac, specs).await
158 }
159 }
160
161 pub async fn read_property_from_devices(
163 &self,
164 requests: Vec<DeviceReadRequest>,
165 max_concurrent: Option<usize>,
166 ) -> Vec<DeviceReadResult> {
167 use futures_util::stream::{self, StreamExt};
168
169 let concurrency = max_concurrent.unwrap_or(DEFAULT_BATCH_CONCURRENCY);
170
171 stream::iter(requests)
172 .map(|req| async move {
173 let result = self
174 .read_property_from_device(
175 req.device_instance,
176 req.object_identifier,
177 req.property_identifier,
178 req.property_array_index,
179 )
180 .await;
181 DeviceReadResult {
182 device_instance: req.device_instance,
183 result,
184 }
185 })
186 .buffer_unordered(concurrency)
187 .collect()
188 .await
189 }
190
191 pub async fn read_property_multiple_from_devices(
197 &self,
198 requests: Vec<DeviceRpmRequest>,
199 max_concurrent: Option<usize>,
200 ) -> Vec<DeviceRpmResult> {
201 use futures_util::stream::{self, StreamExt};
202
203 let concurrency = max_concurrent.unwrap_or(DEFAULT_BATCH_CONCURRENCY);
204
205 stream::iter(requests)
206 .map(|req| async move {
207 let result = self
208 .read_property_multiple_from_device(req.device_instance, req.specs)
209 .await;
210 DeviceRpmResult {
211 device_instance: req.device_instance,
212 result,
213 }
214 })
215 .buffer_unordered(concurrency)
216 .collect()
217 .await
218 }
219
220 pub async fn write_property(
225 &self,
226 destination_mac: &[u8],
227 object_identifier: bacnet_types::primitives::ObjectIdentifier,
228 property_identifier: bacnet_types::enums::PropertyIdentifier,
229 property_array_index: Option<u32>,
230 property_value: Vec<u8>,
231 priority: Option<u8>,
232 ) -> Result<(), Error> {
233 use bacnet_services::write_property::WritePropertyRequest;
234
235 let request = WritePropertyRequest {
236 object_identifier,
237 property_identifier,
238 property_array_index,
239 property_value,
240 priority,
241 };
242 let mut buf = BytesMut::new();
243 request.encode(&mut buf);
244
245 let _ = self
246 .confirmed_request(
247 destination_mac,
248 ConfirmedServiceChoice::WRITE_PROPERTY,
249 &buf,
250 )
251 .await?;
252
253 Ok(())
254 }
255
256 pub async fn write_property_multiple(
258 &self,
259 destination_mac: &[u8],
260 specs: Vec<bacnet_services::wpm::WriteAccessSpecification>,
261 ) -> Result<(), Error> {
262 use bacnet_services::wpm::WritePropertyMultipleRequest;
263
264 let request = WritePropertyMultipleRequest {
265 list_of_write_access_specs: specs,
266 };
267 let mut buf = BytesMut::new();
268 request.encode(&mut buf);
269
270 let _ = self
271 .confirmed_request(
272 destination_mac,
273 ConfirmedServiceChoice::WRITE_PROPERTY_MULTIPLE,
274 &buf,
275 )
276 .await?;
277
278 Ok(())
279 }
280
281 pub async fn write_property_to_device(
287 &self,
288 device_instance: u32,
289 object_identifier: bacnet_types::primitives::ObjectIdentifier,
290 property_identifier: bacnet_types::enums::PropertyIdentifier,
291 property_array_index: Option<u32>,
292 property_value: Vec<u8>,
293 priority: Option<u8>,
294 ) -> Result<(), Error> {
295 let (mac, routing) = self.resolve_device(device_instance).await?;
296
297 if let Some((dnet, dadr)) = routing {
298 use bacnet_services::write_property::WritePropertyRequest;
299
300 let request = WritePropertyRequest {
301 object_identifier,
302 property_identifier,
303 property_array_index,
304 property_value,
305 priority,
306 };
307 let mut buf = BytesMut::new();
308 request.encode(&mut buf);
309
310 let _ = self
311 .confirmed_request_routed(
312 &mac,
313 dnet,
314 &dadr,
315 ConfirmedServiceChoice::WRITE_PROPERTY,
316 &buf,
317 )
318 .await?;
319 Ok(())
320 } else {
321 self.write_property(
322 &mac,
323 object_identifier,
324 property_identifier,
325 property_array_index,
326 property_value,
327 priority,
328 )
329 .await
330 }
331 }
332
333 pub async fn write_property_multiple_to_device(
335 &self,
336 device_instance: u32,
337 specs: Vec<bacnet_services::wpm::WriteAccessSpecification>,
338 ) -> Result<(), Error> {
339 let (mac, routing) = self.resolve_device(device_instance).await?;
340
341 if let Some((dnet, dadr)) = routing {
342 use bacnet_services::wpm::WritePropertyMultipleRequest;
343
344 let request = WritePropertyMultipleRequest {
345 list_of_write_access_specs: specs,
346 };
347 let mut buf = BytesMut::new();
348 request.encode(&mut buf);
349
350 let _ = self
351 .confirmed_request_routed(
352 &mac,
353 dnet,
354 &dadr,
355 ConfirmedServiceChoice::WRITE_PROPERTY_MULTIPLE,
356 &buf,
357 )
358 .await?;
359 Ok(())
360 } else {
361 self.write_property_multiple(&mac, specs).await
362 }
363 }
364 pub async fn write_property_to_devices(
365 &self,
366 requests: Vec<DeviceWriteRequest>,
367 max_concurrent: Option<usize>,
368 ) -> Vec<DeviceWriteResult> {
369 use futures_util::stream::{self, StreamExt};
370
371 let concurrency = max_concurrent.unwrap_or(DEFAULT_BATCH_CONCURRENCY);
372
373 stream::iter(requests)
374 .map(|req| async move {
375 let result = self
376 .write_property_to_device(
377 req.device_instance,
378 req.object_identifier,
379 req.property_identifier,
380 req.property_array_index,
381 req.property_value,
382 req.priority,
383 )
384 .await;
385 DeviceWriteResult {
386 device_instance: req.device_instance,
387 result,
388 }
389 })
390 .buffer_unordered(concurrency)
391 .collect()
392 .await
393 }
394}