1use std::time::Duration;
2
3use crate::{
4 session::{
5 process_service_result, process_unexpected_response,
6 request_builder::{builder_base, builder_debug, builder_error, RequestHeaderBuilder},
7 },
8 Session, UARequest,
9};
10use opcua_core::ResponseMessage;
11use opcua_types::{
12 BrowseDescription, BrowseNextRequest, BrowseNextResponse, BrowsePath, BrowsePathResult,
13 BrowseRequest, BrowseResponse, BrowseResult, ByteString, Error, IntegerId, NodeId,
14 RegisterNodesRequest, RegisterNodesResponse, StatusCode, TranslateBrowsePathsToNodeIdsRequest,
15 TranslateBrowsePathsToNodeIdsResponse, UnregisterNodesRequest, UnregisterNodesResponse,
16 ViewDescription,
17};
18use tracing::{debug_span, Instrument};
19
20#[derive(Debug, Clone)]
21pub struct Browse {
25 nodes_to_browse: Vec<BrowseDescription>,
26 view: ViewDescription,
27 max_references_per_node: u32,
28
29 header: RequestHeaderBuilder,
30}
31
32builder_base!(Browse);
33
34impl Browse {
35 pub fn new(session: &Session) -> Self {
37 Self {
38 nodes_to_browse: Vec::new(),
39 view: ViewDescription::default(),
40 max_references_per_node: 0,
41
42 header: RequestHeaderBuilder::new_from_session(session),
43 }
44 }
45
46 pub fn new_manual(
48 session_id: u32,
49 timeout: Duration,
50 auth_token: NodeId,
51 request_handle: IntegerId,
52 ) -> Self {
53 Self {
54 nodes_to_browse: Vec::new(),
55 view: ViewDescription::default(),
56 max_references_per_node: 0,
57
58 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
59 }
60 }
61
62 pub fn view(mut self, view: ViewDescription) -> Self {
64 self.view = view;
65 self
66 }
67
68 pub fn max_references_per_node(mut self, max_references_per_node: u32) -> Self {
70 self.max_references_per_node = max_references_per_node;
71 self
72 }
73
74 pub fn nodes_to_browse(mut self, nodes_to_browse: Vec<BrowseDescription>) -> Self {
76 self.nodes_to_browse = nodes_to_browse;
77 self
78 }
79
80 pub fn browse_node(mut self, node_to_browse: impl Into<BrowseDescription>) -> Self {
82 self.nodes_to_browse.push(node_to_browse.into());
83 self
84 }
85}
86
87impl UARequest for Browse {
88 type Out = BrowseResponse;
89
90 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
91 where
92 Self: 'a,
93 {
94 let span = debug_span!(
95 "Sending Browse request",
96 num_nodes_to_browse = self.nodes_to_browse.len()
97 );
98 let request = {
99 let _h = span.enter();
100 if self.nodes_to_browse.is_empty() {
101 builder_error!(self, "browse was not supplied with any nodes to browse");
102 return Err(Error::new(
103 StatusCode::BadNothingToDo,
104 "browse was not supplied with any nodes to browse",
105 ));
106 }
107 BrowseRequest {
108 request_header: self.header.header,
109 view: self.view,
110 requested_max_references_per_node: self.max_references_per_node,
111 nodes_to_browse: Some(self.nodes_to_browse),
112 }
113 };
114 let response = channel
115 .send(request, self.header.timeout)
116 .instrument(span.clone())
117 .await?;
118 let _h = span.enter();
119 if let ResponseMessage::Browse(response) = response {
120 builder_debug!(self, "browse, success");
121 process_service_result(&response.response_header)?;
122 Ok(*response)
123 } else {
124 builder_error!(self, "browse failed");
125 Err(process_unexpected_response(response))
126 }
127 }
128}
129
130#[derive(Debug, Clone)]
131pub struct BrowseNext {
136 continuation_points: Vec<ByteString>,
137 release_continuation_points: bool,
138
139 header: RequestHeaderBuilder,
140}
141
142builder_base!(BrowseNext);
143
144impl BrowseNext {
145 pub fn new(session: &Session) -> Self {
147 Self {
148 continuation_points: Vec::new(),
149 release_continuation_points: false,
150
151 header: RequestHeaderBuilder::new_from_session(session),
152 }
153 }
154
155 pub fn new_manual(
157 session_id: u32,
158 timeout: Duration,
159 auth_token: NodeId,
160 request_handle: IntegerId,
161 ) -> Self {
162 Self {
163 continuation_points: Vec::new(),
164 release_continuation_points: false,
165
166 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
167 }
168 }
169
170 pub fn release_continuation_points(mut self, release_continuation_points: bool) -> Self {
173 self.release_continuation_points = release_continuation_points;
174 self
175 }
176
177 pub fn continuation_points(mut self, continuation_points: Vec<ByteString>) -> Self {
179 self.continuation_points = continuation_points;
180 self
181 }
182
183 pub fn continuation_point(mut self, continuation_point: ByteString) -> Self {
185 self.continuation_points.push(continuation_point);
186 self
187 }
188}
189
190impl UARequest for BrowseNext {
191 type Out = BrowseNextResponse;
192
193 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
194 where
195 Self: 'a,
196 {
197 let span = debug_span!(
198 "Sending BrowseNext request",
199 num_continuation_points = self.continuation_points.len(),
200 release_continuation_points = self.release_continuation_points
201 );
202 let request = {
203 let _h = span.enter();
204 if self.continuation_points.is_empty() {
205 builder_error!(
206 self,
207 "browse_next was not supplied with any continuation points"
208 );
209 return Err(Error::new(
210 StatusCode::BadNothingToDo,
211 "browse_next was not supplied with any continuation points",
212 ));
213 }
214 BrowseNextRequest {
215 request_header: self.header.header,
216 continuation_points: Some(self.continuation_points),
217 release_continuation_points: self.release_continuation_points,
218 }
219 };
220 let response = channel
221 .send(request, self.header.timeout)
222 .instrument(span.clone())
223 .await?;
224 let _h = span.enter();
225 if let ResponseMessage::BrowseNext(response) = response {
226 builder_debug!(self, "browse_next, success");
227 process_service_result(&response.response_header)?;
228 Ok(*response)
229 } else {
230 builder_error!(self, "browse_next failed");
231 Err(process_unexpected_response(response))
232 }
233 }
234}
235
236#[derive(Debug, Clone)]
237pub struct TranslateBrowsePaths {
244 browse_paths: Vec<BrowsePath>,
245
246 header: RequestHeaderBuilder,
247}
248
249builder_base!(TranslateBrowsePaths);
250
251impl TranslateBrowsePaths {
252 pub fn new(session: &Session) -> Self {
254 Self {
255 browse_paths: Vec::new(),
256
257 header: RequestHeaderBuilder::new_from_session(session),
258 }
259 }
260
261 pub fn new_manual(
263 session_id: u32,
264 timeout: Duration,
265 auth_token: NodeId,
266 request_handle: IntegerId,
267 ) -> Self {
268 Self {
269 browse_paths: Vec::new(),
270
271 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
272 }
273 }
274
275 pub fn browse_paths(mut self, browse_paths: Vec<BrowsePath>) -> Self {
277 self.browse_paths = browse_paths;
278 self
279 }
280
281 pub fn browse_path(mut self, browse_path: BrowsePath) -> Self {
283 self.browse_paths.push(browse_path);
284 self
285 }
286}
287
288impl UARequest for TranslateBrowsePaths {
289 type Out = TranslateBrowsePathsToNodeIdsResponse;
290
291 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
292 where
293 Self: 'a,
294 {
295 let span = debug_span!(
296 "Sending TranslateBrowsePathsToNodeIds request",
297 num_browse_paths = self.browse_paths.len()
298 );
299 let request = {
300 let _h = span.enter();
301 if self.browse_paths.is_empty() {
302 builder_error!(
303 self,
304 "translate_browse_paths_to_node_ids was not supplied with any browse paths"
305 );
306 return Err(Error::new(
307 StatusCode::BadNothingToDo,
308 "translate_browse_paths_to_node_ids was not supplied with any browse paths",
309 ));
310 }
311 TranslateBrowsePathsToNodeIdsRequest {
312 request_header: self.header.header,
313 browse_paths: Some(self.browse_paths),
314 }
315 };
316 let response = channel
317 .send(request, self.header.timeout)
318 .instrument(span.clone())
319 .await?;
320 let _h = span.enter();
321 if let ResponseMessage::TranslateBrowsePathsToNodeIds(response) = response {
322 builder_debug!(self, "translate_browse_paths_to_node_ids, success");
323 process_service_result(&response.response_header)?;
324 Ok(*response)
325 } else {
326 builder_error!(self, "translate_browse_paths_to_node_ids failed");
327 Err(process_unexpected_response(response))
328 }
329 }
330}
331
332#[derive(Debug, Clone)]
333pub struct RegisterNodes {
339 nodes_to_register: Vec<NodeId>,
340
341 header: RequestHeaderBuilder,
342}
343
344builder_base!(RegisterNodes);
345
346impl RegisterNodes {
347 pub fn new(session: &Session) -> Self {
349 Self {
350 nodes_to_register: Vec::new(),
351
352 header: RequestHeaderBuilder::new_from_session(session),
353 }
354 }
355
356 pub fn new_manual(
358 session_id: u32,
359 timeout: Duration,
360 auth_token: NodeId,
361 request_handle: IntegerId,
362 ) -> Self {
363 Self {
364 nodes_to_register: Vec::new(),
365
366 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
367 }
368 }
369
370 pub fn nodes_to_register(mut self, nodes_to_register: Vec<NodeId>) -> Self {
372 self.nodes_to_register = nodes_to_register;
373 self
374 }
375
376 pub fn node_to_register(mut self, node_to_register: impl Into<NodeId>) -> Self {
378 self.nodes_to_register.push(node_to_register.into());
379 self
380 }
381}
382
383impl UARequest for RegisterNodes {
384 type Out = RegisterNodesResponse;
385
386 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
387 where
388 Self: 'a,
389 {
390 let span = debug_span!(
391 "Sending RegisterNodes request",
392 num_nodes_to_register = self.nodes_to_register.len()
393 );
394 let request = {
395 let _h = span.enter();
396 if self.nodes_to_register.is_empty() {
397 builder_error!(self, "register_nodes was not supplied with any node IDs");
398 return Err(Error::new(
399 StatusCode::BadNothingToDo,
400 "register_nodes was not supplied with any node IDs",
401 ));
402 }
403 RegisterNodesRequest {
404 request_header: self.header.header,
405 nodes_to_register: Some(self.nodes_to_register),
406 }
407 };
408 let response = channel
409 .send(request, self.header.timeout)
410 .instrument(span.clone())
411 .await?;
412 let _h = span.enter();
413 if let ResponseMessage::RegisterNodes(response) = response {
414 builder_debug!(self, "register_nodes, success");
415 process_service_result(&response.response_header)?;
416 Ok(*response)
417 } else {
418 builder_error!(self, "register_nodes failed");
419 Err(process_unexpected_response(response))
420 }
421 }
422}
423
424#[derive(Debug, Clone)]
425pub struct UnregisterNodes {
431 nodes_to_unregister: Vec<NodeId>,
432
433 header: RequestHeaderBuilder,
434}
435
436builder_base!(UnregisterNodes);
437
438impl UnregisterNodes {
439 pub fn new(session: &Session) -> Self {
441 Self {
442 nodes_to_unregister: Vec::new(),
443
444 header: RequestHeaderBuilder::new_from_session(session),
445 }
446 }
447
448 pub fn new_manual(
450 session_id: u32,
451 timeout: Duration,
452 auth_token: NodeId,
453 request_handle: IntegerId,
454 ) -> Self {
455 Self {
456 nodes_to_unregister: Vec::new(),
457
458 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
459 }
460 }
461
462 pub fn nodes_to_unregister(mut self, nodes_to_unregister: Vec<NodeId>) -> Self {
464 self.nodes_to_unregister = nodes_to_unregister;
465 self
466 }
467
468 pub fn node_to_unregister(mut self, node_to_unregister: impl Into<NodeId>) -> Self {
470 self.nodes_to_unregister.push(node_to_unregister.into());
471 self
472 }
473}
474
475impl UARequest for UnregisterNodes {
476 type Out = UnregisterNodesResponse;
477
478 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
479 where
480 Self: 'a,
481 {
482 let span = debug_span!(
483 "Sending UnregisterNodes request",
484 num_nodes_to_unregister = self.nodes_to_unregister.len()
485 );
486 let request = {
487 let _h = span.enter();
488 if self.nodes_to_unregister.is_empty() {
489 builder_error!(self, "unregister_nodes was not supplied with any node IDs");
490 return Err(Error::new(
491 StatusCode::BadNothingToDo,
492 "unregister_nodes was not supplied with any node IDs",
493 ));
494 }
495 UnregisterNodesRequest {
496 request_header: self.header.header,
497 nodes_to_unregister: Some(self.nodes_to_unregister),
498 }
499 };
500 let response = channel
501 .send(request, self.header.timeout)
502 .instrument(span.clone())
503 .await?;
504 let _h = span.enter();
505 if let ResponseMessage::UnregisterNodes(response) = response {
506 builder_debug!(self, "unregister_nodes, success");
507 process_service_result(&response.response_header)?;
508 Ok(*response)
509 } else {
510 builder_error!(self, "unregister_nodes failed");
511 Err(process_unexpected_response(response))
512 }
513 }
514}
515
516impl Session {
517 pub async fn browse(
532 &self,
533 nodes_to_browse: &[BrowseDescription],
534 max_references_per_node: u32,
535 view: Option<ViewDescription>,
536 ) -> Result<Vec<BrowseResult>, Error> {
537 Ok(Browse::new(self)
538 .nodes_to_browse(nodes_to_browse.to_vec())
539 .view(view.unwrap_or_default())
540 .max_references_per_node(max_references_per_node)
541 .send(&self.channel)
542 .await?
543 .results
544 .unwrap_or_default())
545 }
546
547 pub async fn browse_next(
564 &self,
565 release_continuation_points: bool,
566 continuation_points: &[ByteString],
567 ) -> Result<Vec<BrowseResult>, Error> {
568 Ok(BrowseNext::new(self)
569 .continuation_points(continuation_points.to_vec())
570 .release_continuation_points(release_continuation_points)
571 .send(&self.channel)
572 .await?
573 .results
574 .unwrap_or_default())
575 }
576
577 pub async fn translate_browse_paths_to_node_ids(
596 &self,
597 browse_paths: &[BrowsePath],
598 ) -> Result<Vec<BrowsePathResult>, Error> {
599 Ok(TranslateBrowsePaths::new(self)
600 .browse_paths(browse_paths.to_vec())
601 .send(&self.channel)
602 .await?
603 .results
604 .unwrap_or_default())
605 }
606
607 pub async fn register_nodes(&self, nodes_to_register: &[NodeId]) -> Result<Vec<NodeId>, Error> {
624 Ok(RegisterNodes::new(self)
625 .nodes_to_register(nodes_to_register.to_vec())
626 .send(&self.channel)
627 .await?
628 .registered_node_ids
629 .unwrap_or_default())
630 }
631
632 pub async fn unregister_nodes(&self, nodes_to_unregister: &[NodeId]) -> Result<(), Error> {
648 UnregisterNodes::new(self)
649 .nodes_to_unregister(nodes_to_unregister.to_vec())
650 .send(&self.channel)
651 .await?;
652 Ok(())
653 }
654}