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, IntegerId, NodeId,
14 RegisterNodesRequest, RegisterNodesResponse, StatusCode, TranslateBrowsePathsToNodeIdsRequest,
15 TranslateBrowsePathsToNodeIdsResponse, UnregisterNodesRequest, UnregisterNodesResponse,
16 ViewDescription,
17};
18
19#[derive(Debug, Clone)]
20pub struct Browse {
24 nodes_to_browse: Vec<BrowseDescription>,
25 view: ViewDescription,
26 max_references_per_node: u32,
27
28 header: RequestHeaderBuilder,
29}
30
31builder_base!(Browse);
32
33impl Browse {
34 pub fn new(session: &Session) -> Self {
36 Self {
37 nodes_to_browse: Vec::new(),
38 view: ViewDescription::default(),
39 max_references_per_node: 0,
40
41 header: RequestHeaderBuilder::new_from_session(session),
42 }
43 }
44
45 pub fn new_manual(
47 session_id: u32,
48 timeout: Duration,
49 auth_token: NodeId,
50 request_handle: IntegerId,
51 ) -> Self {
52 Self {
53 nodes_to_browse: Vec::new(),
54 view: ViewDescription::default(),
55 max_references_per_node: 0,
56
57 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
58 }
59 }
60
61 pub fn view(mut self, view: ViewDescription) -> Self {
63 self.view = view;
64 self
65 }
66
67 pub fn max_references_per_node(mut self, max_references_per_node: u32) -> Self {
69 self.max_references_per_node = max_references_per_node;
70 self
71 }
72
73 pub fn nodes_to_browse(mut self, nodes_to_browse: Vec<BrowseDescription>) -> Self {
75 self.nodes_to_browse = nodes_to_browse;
76 self
77 }
78
79 pub fn browse_node(mut self, node_to_browse: impl Into<BrowseDescription>) -> Self {
81 self.nodes_to_browse.push(node_to_browse.into());
82 self
83 }
84}
85
86impl UARequest for Browse {
87 type Out = BrowseResponse;
88
89 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, StatusCode>
90 where
91 Self: 'a,
92 {
93 if self.nodes_to_browse.is_empty() {
94 builder_error!(self, "browse was not supplied with any nodes to browse");
95 return Err(StatusCode::BadNothingToDo);
96 }
97 let request = BrowseRequest {
98 request_header: self.header.header,
99 view: self.view,
100 requested_max_references_per_node: self.max_references_per_node,
101 nodes_to_browse: Some(self.nodes_to_browse),
102 };
103 let response = channel.send(request, self.header.timeout).await?;
104 if let ResponseMessage::Browse(response) = response {
105 builder_debug!(self, "browse, success");
106 process_service_result(&response.response_header)?;
107 Ok(*response)
108 } else {
109 builder_error!(self, "browse failed");
110 Err(process_unexpected_response(response))
111 }
112 }
113}
114
115#[derive(Debug, Clone)]
116pub struct BrowseNext {
121 continuation_points: Vec<ByteString>,
122 release_continuation_points: bool,
123
124 header: RequestHeaderBuilder,
125}
126
127builder_base!(BrowseNext);
128
129impl BrowseNext {
130 pub fn new(session: &Session) -> Self {
132 Self {
133 continuation_points: Vec::new(),
134 release_continuation_points: false,
135
136 header: RequestHeaderBuilder::new_from_session(session),
137 }
138 }
139
140 pub fn new_manual(
142 session_id: u32,
143 timeout: Duration,
144 auth_token: NodeId,
145 request_handle: IntegerId,
146 ) -> Self {
147 Self {
148 continuation_points: Vec::new(),
149 release_continuation_points: false,
150
151 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
152 }
153 }
154
155 pub fn release_continuation_points(mut self, release_continuation_points: bool) -> Self {
158 self.release_continuation_points = release_continuation_points;
159 self
160 }
161
162 pub fn continuation_points(mut self, continuation_points: Vec<ByteString>) -> Self {
164 self.continuation_points = continuation_points;
165 self
166 }
167
168 pub fn continuation_point(mut self, continuation_point: ByteString) -> Self {
170 self.continuation_points.push(continuation_point);
171 self
172 }
173}
174
175impl UARequest for BrowseNext {
176 type Out = BrowseNextResponse;
177
178 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, StatusCode>
179 where
180 Self: 'a,
181 {
182 if self.continuation_points.is_empty() {
183 builder_error!(
184 self,
185 "browse_next was not supplied with any continuation points"
186 );
187 return Err(StatusCode::BadNothingToDo);
188 }
189 let request = BrowseNextRequest {
190 request_header: self.header.header,
191 continuation_points: Some(self.continuation_points),
192 release_continuation_points: self.release_continuation_points,
193 };
194 let response = channel.send(request, self.header.timeout).await?;
195 if let ResponseMessage::BrowseNext(response) = response {
196 builder_debug!(self, "browse_next, success");
197 process_service_result(&response.response_header)?;
198 Ok(*response)
199 } else {
200 builder_error!(self, "browse_next failed");
201 Err(process_unexpected_response(response))
202 }
203 }
204}
205
206#[derive(Debug, Clone)]
207pub struct TranslateBrowsePaths {
214 browse_paths: Vec<BrowsePath>,
215
216 header: RequestHeaderBuilder,
217}
218
219builder_base!(TranslateBrowsePaths);
220
221impl TranslateBrowsePaths {
222 pub fn new(session: &Session) -> Self {
224 Self {
225 browse_paths: Vec::new(),
226
227 header: RequestHeaderBuilder::new_from_session(session),
228 }
229 }
230
231 pub fn new_manual(
233 session_id: u32,
234 timeout: Duration,
235 auth_token: NodeId,
236 request_handle: IntegerId,
237 ) -> Self {
238 Self {
239 browse_paths: Vec::new(),
240
241 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
242 }
243 }
244
245 pub fn browse_paths(mut self, browse_paths: Vec<BrowsePath>) -> Self {
247 self.browse_paths = browse_paths;
248 self
249 }
250
251 pub fn browse_path(mut self, browse_path: BrowsePath) -> Self {
253 self.browse_paths.push(browse_path);
254 self
255 }
256}
257
258impl UARequest for TranslateBrowsePaths {
259 type Out = TranslateBrowsePathsToNodeIdsResponse;
260
261 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, StatusCode>
262 where
263 Self: 'a,
264 {
265 if self.browse_paths.is_empty() {
266 builder_error!(
267 self,
268 "translate_browse_paths_to_node_ids was not supplied with any browse paths"
269 );
270 return Err(StatusCode::BadNothingToDo);
271 }
272 let request = TranslateBrowsePathsToNodeIdsRequest {
273 request_header: self.header.header,
274 browse_paths: Some(self.browse_paths),
275 };
276 let response = channel.send(request, self.header.timeout).await?;
277 if let ResponseMessage::TranslateBrowsePathsToNodeIds(response) = response {
278 builder_debug!(self, "translate_browse_paths_to_node_ids, success");
279 process_service_result(&response.response_header)?;
280 Ok(*response)
281 } else {
282 builder_error!(self, "translate_browse_paths_to_node_ids failed");
283 Err(process_unexpected_response(response))
284 }
285 }
286}
287
288#[derive(Debug, Clone)]
289pub struct RegisterNodes {
295 nodes_to_register: Vec<NodeId>,
296
297 header: RequestHeaderBuilder,
298}
299
300builder_base!(RegisterNodes);
301
302impl RegisterNodes {
303 pub fn new(session: &Session) -> Self {
305 Self {
306 nodes_to_register: Vec::new(),
307
308 header: RequestHeaderBuilder::new_from_session(session),
309 }
310 }
311
312 pub fn new_manual(
314 session_id: u32,
315 timeout: Duration,
316 auth_token: NodeId,
317 request_handle: IntegerId,
318 ) -> Self {
319 Self {
320 nodes_to_register: Vec::new(),
321
322 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
323 }
324 }
325
326 pub fn nodes_to_register(mut self, nodes_to_register: Vec<NodeId>) -> Self {
328 self.nodes_to_register = nodes_to_register;
329 self
330 }
331
332 pub fn node_to_register(mut self, node_to_register: impl Into<NodeId>) -> Self {
334 self.nodes_to_register.push(node_to_register.into());
335 self
336 }
337}
338
339impl UARequest for RegisterNodes {
340 type Out = RegisterNodesResponse;
341
342 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, StatusCode>
343 where
344 Self: 'a,
345 {
346 if self.nodes_to_register.is_empty() {
347 builder_error!(self, "register_nodes was not supplied with any node IDs");
348 return Err(StatusCode::BadNothingToDo);
349 }
350 let request = RegisterNodesRequest {
351 request_header: self.header.header,
352 nodes_to_register: Some(self.nodes_to_register),
353 };
354 let response = channel.send(request, self.header.timeout).await?;
355 if let ResponseMessage::RegisterNodes(response) = response {
356 builder_debug!(self, "register_nodes, success");
357 process_service_result(&response.response_header)?;
358 Ok(*response)
359 } else {
360 builder_error!(self, "register_nodes failed");
361 Err(process_unexpected_response(response))
362 }
363 }
364}
365
366#[derive(Debug, Clone)]
367pub struct UnregisterNodes {
373 nodes_to_unregister: Vec<NodeId>,
374
375 header: RequestHeaderBuilder,
376}
377
378builder_base!(UnregisterNodes);
379
380impl UnregisterNodes {
381 pub fn new(session: &Session) -> Self {
383 Self {
384 nodes_to_unregister: Vec::new(),
385
386 header: RequestHeaderBuilder::new_from_session(session),
387 }
388 }
389
390 pub fn new_manual(
392 session_id: u32,
393 timeout: Duration,
394 auth_token: NodeId,
395 request_handle: IntegerId,
396 ) -> Self {
397 Self {
398 nodes_to_unregister: Vec::new(),
399
400 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
401 }
402 }
403
404 pub fn nodes_to_unregister(mut self, nodes_to_unregister: Vec<NodeId>) -> Self {
406 self.nodes_to_unregister = nodes_to_unregister;
407 self
408 }
409
410 pub fn node_to_unregister(mut self, node_to_unregister: impl Into<NodeId>) -> Self {
412 self.nodes_to_unregister.push(node_to_unregister.into());
413 self
414 }
415}
416
417impl UARequest for UnregisterNodes {
418 type Out = UnregisterNodesResponse;
419
420 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, StatusCode>
421 where
422 Self: 'a,
423 {
424 if self.nodes_to_unregister.is_empty() {
425 builder_error!(self, "unregister_nodes was not supplied with any node IDs");
426 return Err(StatusCode::BadNothingToDo);
427 }
428 let request = UnregisterNodesRequest {
429 request_header: self.header.header,
430 nodes_to_unregister: Some(self.nodes_to_unregister),
431 };
432 let response = channel.send(request, self.header.timeout).await?;
433 if let ResponseMessage::UnregisterNodes(response) = response {
434 builder_debug!(self, "unregister_nodes, success");
435 process_service_result(&response.response_header)?;
436 Ok(*response)
437 } else {
438 builder_error!(self, "unregister_nodes failed");
439 Err(process_unexpected_response(response))
440 }
441 }
442}
443
444impl Session {
445 pub async fn browse(
460 &self,
461 nodes_to_browse: &[BrowseDescription],
462 max_references_per_node: u32,
463 view: Option<ViewDescription>,
464 ) -> Result<Vec<BrowseResult>, StatusCode> {
465 Ok(Browse::new(self)
466 .nodes_to_browse(nodes_to_browse.to_vec())
467 .view(view.unwrap_or_default())
468 .max_references_per_node(max_references_per_node)
469 .send(&self.channel)
470 .await?
471 .results
472 .unwrap_or_default())
473 }
474
475 pub async fn browse_next(
492 &self,
493 release_continuation_points: bool,
494 continuation_points: &[ByteString],
495 ) -> Result<Vec<BrowseResult>, StatusCode> {
496 Ok(BrowseNext::new(self)
497 .continuation_points(continuation_points.to_vec())
498 .release_continuation_points(release_continuation_points)
499 .send(&self.channel)
500 .await?
501 .results
502 .unwrap_or_default())
503 }
504
505 pub async fn translate_browse_paths_to_node_ids(
524 &self,
525 browse_paths: &[BrowsePath],
526 ) -> Result<Vec<BrowsePathResult>, StatusCode> {
527 Ok(TranslateBrowsePaths::new(self)
528 .browse_paths(browse_paths.to_vec())
529 .send(&self.channel)
530 .await?
531 .results
532 .unwrap_or_default())
533 }
534
535 pub async fn register_nodes(
552 &self,
553 nodes_to_register: &[NodeId],
554 ) -> Result<Vec<NodeId>, StatusCode> {
555 Ok(RegisterNodes::new(self)
556 .nodes_to_register(nodes_to_register.to_vec())
557 .send(&self.channel)
558 .await?
559 .registered_node_ids
560 .unwrap_or_default())
561 }
562
563 pub async fn unregister_nodes(&self, nodes_to_unregister: &[NodeId]) -> Result<(), StatusCode> {
579 UnregisterNodes::new(self)
580 .nodes_to_unregister(nodes_to_unregister.to_vec())
581 .send(&self.channel)
582 .await?;
583 Ok(())
584 }
585}