opcua_client/session/services/
node_management.rs1use 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};
10
11use opcua_core::ResponseMessage;
12use opcua_types::{
13 AddNodesItem, AddNodesRequest, AddNodesResponse, AddNodesResult, AddReferencesItem,
14 AddReferencesRequest, AddReferencesResponse, DeleteNodesItem, DeleteNodesRequest,
15 DeleteNodesResponse, DeleteReferencesItem, DeleteReferencesRequest, DeleteReferencesResponse,
16 IntegerId, NodeId, StatusCode,
17};
18
19#[derive(Debug, Clone)]
20pub struct AddNodes {
24 nodes_to_add: Vec<AddNodesItem>,
25
26 header: RequestHeaderBuilder,
27}
28
29builder_base!(AddNodes);
30
31impl AddNodes {
32 pub fn new(session: &Session) -> Self {
34 Self {
35 nodes_to_add: Vec::new(),
36 header: RequestHeaderBuilder::new_from_session(session),
37 }
38 }
39
40 pub fn new_manual(
42 session_id: u32,
43 timeout: Duration,
44 auth_token: NodeId,
45 request_handle: IntegerId,
46 ) -> Self {
47 Self {
48 nodes_to_add: Vec::new(),
49 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
50 }
51 }
52
53 pub fn nodes_to_add(mut self, nodes_to_add: Vec<AddNodesItem>) -> Self {
55 self.nodes_to_add = nodes_to_add;
56 self
57 }
58
59 pub fn node(mut self, node: impl Into<AddNodesItem>) -> Self {
61 self.nodes_to_add.push(node.into());
62 self
63 }
64}
65
66impl UARequest for AddNodes {
67 type Out = AddNodesResponse;
68
69 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, StatusCode>
70 where
71 Self: 'a,
72 {
73 if self.nodes_to_add.is_empty() {
74 builder_error!(self, "add_nodes, called with no nodes to add");
75 return Err(StatusCode::BadNothingToDo);
76 }
77 let request = AddNodesRequest {
78 request_header: self.header.header,
79 nodes_to_add: Some(self.nodes_to_add),
80 };
81 let response = channel.send(request, self.header.timeout).await?;
82 if let ResponseMessage::AddNodes(response) = response {
83 builder_debug!(self, "add_nodes, success");
84 process_service_result(&response.response_header)?;
85 Ok(*response)
86 } else {
87 builder_error!(self, "add_nodes failed");
88 Err(process_unexpected_response(response))
89 }
90 }
91}
92
93#[derive(Debug, Clone)]
94pub struct AddReferences {
98 references_to_add: Vec<AddReferencesItem>,
99
100 header: RequestHeaderBuilder,
101}
102
103builder_base!(AddReferences);
104
105impl AddReferences {
106 pub fn new(session: &Session) -> Self {
108 Self {
109 references_to_add: Vec::new(),
110 header: RequestHeaderBuilder::new_from_session(session),
111 }
112 }
113
114 pub fn new_manual(
116 session_id: u32,
117 timeout: Duration,
118 auth_token: NodeId,
119 request_handle: IntegerId,
120 ) -> Self {
121 Self {
122 references_to_add: Vec::new(),
123 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
124 }
125 }
126
127 pub fn references_to_add(mut self, references_to_add: Vec<AddReferencesItem>) -> Self {
129 self.references_to_add = references_to_add;
130 self
131 }
132
133 pub fn reference(mut self, reference: impl Into<AddReferencesItem>) -> Self {
135 self.references_to_add.push(reference.into());
136 self
137 }
138}
139
140impl UARequest for AddReferences {
141 type Out = AddReferencesResponse;
142
143 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, StatusCode>
144 where
145 Self: 'a,
146 {
147 if self.references_to_add.is_empty() {
148 builder_error!(self, "add_references, called with no references to add");
149 return Err(StatusCode::BadNothingToDo);
150 }
151 let request = AddReferencesRequest {
152 request_header: self.header.header,
153 references_to_add: Some(self.references_to_add),
154 };
155 let response = channel.send(request, self.header.timeout).await?;
156 if let ResponseMessage::AddReferences(response) = response {
157 builder_debug!(self, "add_references, success");
158 process_service_result(&response.response_header)?;
159 Ok(*response)
160 } else {
161 builder_error!(self, "add_references failed");
162 Err(process_unexpected_response(response))
163 }
164 }
165}
166
167#[derive(Debug, Clone)]
168pub struct DeleteNodes {
172 nodes_to_delete: Vec<DeleteNodesItem>,
173
174 header: RequestHeaderBuilder,
175}
176
177builder_base!(DeleteNodes);
178
179impl DeleteNodes {
180 pub fn new(session: &Session) -> Self {
182 Self {
183 nodes_to_delete: Vec::new(),
184 header: RequestHeaderBuilder::new_from_session(session),
185 }
186 }
187
188 pub fn new_manual(
190 session_id: u32,
191 timeout: Duration,
192 auth_token: NodeId,
193 request_handle: IntegerId,
194 ) -> Self {
195 Self {
196 nodes_to_delete: Vec::new(),
197 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
198 }
199 }
200
201 pub fn nodes_to_delete(mut self, nodes_to_delete: Vec<DeleteNodesItem>) -> Self {
203 self.nodes_to_delete = nodes_to_delete;
204 self
205 }
206
207 pub fn node(mut self, reference: impl Into<DeleteNodesItem>) -> Self {
209 self.nodes_to_delete.push(reference.into());
210 self
211 }
212}
213
214impl UARequest for DeleteNodes {
215 type Out = DeleteNodesResponse;
216
217 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, StatusCode>
218 where
219 Self: 'a,
220 {
221 if self.nodes_to_delete.is_empty() {
222 builder_error!(self, "delete_nodes, called with no nodes to delete");
223 return Err(StatusCode::BadNothingToDo);
224 }
225 let request = DeleteNodesRequest {
226 request_header: self.header.header,
227 nodes_to_delete: Some(self.nodes_to_delete),
228 };
229 let response = channel.send(request, self.header.timeout).await?;
230 if let ResponseMessage::DeleteNodes(response) = response {
231 builder_debug!(self, "delete_nodes, success");
232 process_service_result(&response.response_header)?;
233 Ok(*response)
234 } else {
235 builder_error!(self, "delete_nodes failed");
236 Err(process_unexpected_response(response))
237 }
238 }
239}
240
241#[derive(Debug, Clone)]
242pub struct DeleteReferences {
246 references_to_delete: Vec<DeleteReferencesItem>,
247
248 header: RequestHeaderBuilder,
249}
250
251builder_base!(DeleteReferences);
252
253impl DeleteReferences {
254 pub fn new(session: &Session) -> Self {
256 Self {
257 references_to_delete: Vec::new(),
258 header: RequestHeaderBuilder::new_from_session(session),
259 }
260 }
261
262 pub fn new_manual(
264 session_id: u32,
265 timeout: Duration,
266 auth_token: NodeId,
267 request_handle: IntegerId,
268 ) -> Self {
269 Self {
270 references_to_delete: Vec::new(),
271 header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
272 }
273 }
274
275 pub fn references_to_delete(mut self, references_to_delete: Vec<DeleteReferencesItem>) -> Self {
277 self.references_to_delete = references_to_delete;
278 self
279 }
280
281 pub fn reference(mut self, reference: impl Into<DeleteReferencesItem>) -> Self {
283 self.references_to_delete.push(reference.into());
284 self
285 }
286}
287
288impl UARequest for DeleteReferences {
289 type Out = DeleteReferencesResponse;
290
291 async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, StatusCode>
292 where
293 Self: 'a,
294 {
295 if self.references_to_delete.is_empty() {
296 builder_error!(
297 self,
298 "delete_references, called with no references to delete"
299 );
300 return Err(StatusCode::BadNothingToDo);
301 }
302 let request = DeleteReferencesRequest {
303 request_header: self.header.header,
304 references_to_delete: Some(self.references_to_delete),
305 };
306 let response = channel.send(request, self.header.timeout).await?;
307 if let ResponseMessage::DeleteReferences(response) = response {
308 builder_debug!(self, "delete_references, success");
309 process_service_result(&response.response_header)?;
310 Ok(*response)
311 } else {
312 builder_error!(self, "delete_references failed");
313 Err(process_unexpected_response(response))
314 }
315 }
316}
317
318impl Session {
319 pub async fn add_nodes(
333 &self,
334 nodes_to_add: &[AddNodesItem],
335 ) -> Result<Vec<AddNodesResult>, StatusCode> {
336 Ok(AddNodes::new(self)
337 .nodes_to_add(nodes_to_add.to_vec())
338 .send(&self.channel)
339 .await?
340 .results
341 .unwrap_or_default())
342 }
343
344 pub async fn add_references(
358 &self,
359 references_to_add: &[AddReferencesItem],
360 ) -> Result<Vec<StatusCode>, StatusCode> {
361 Ok(AddReferences::new(self)
362 .references_to_add(references_to_add.to_vec())
363 .send(&self.channel)
364 .await?
365 .results
366 .unwrap_or_default())
367 }
368
369 pub async fn delete_nodes(
383 &self,
384 nodes_to_delete: &[DeleteNodesItem],
385 ) -> Result<Vec<StatusCode>, StatusCode> {
386 Ok(DeleteNodes::new(self)
387 .nodes_to_delete(nodes_to_delete.to_vec())
388 .send(&self.channel)
389 .await?
390 .results
391 .unwrap_or_default())
392 }
393
394 pub async fn delete_references(
408 &self,
409 references_to_delete: &[DeleteReferencesItem],
410 ) -> Result<Vec<StatusCode>, StatusCode> {
411 Ok(DeleteReferences::new(self)
412 .references_to_delete(references_to_delete.to_vec())
413 .send(&self.channel)
414 .await?
415 .results
416 .unwrap_or_default())
417 }
418}