Skip to main content

opcua/client/session/
services.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2022 Adam Lock
4
5use std::{convert::TryFrom, sync::mpsc::SyncSender};
6
7use crate::{
8    client::callbacks::OnSubscriptionNotification,
9    core::supported_message::SupportedMessage,
10    types::{
11        node_ids::{MethodId, ObjectId},
12        status_code::StatusCode,
13        *,
14    },
15};
16
17/// Enumeration used with Session::history_read()
18pub enum HistoryReadAction {
19    ReadEventDetails(ReadEventDetails),
20    ReadRawModifiedDetails(ReadRawModifiedDetails),
21    ReadProcessedDetails(ReadProcessedDetails),
22    ReadAtTimeDetails(ReadAtTimeDetails),
23}
24
25impl From<HistoryReadAction> for ExtensionObject {
26    fn from(action: HistoryReadAction) -> Self {
27        match action {
28            HistoryReadAction::ReadEventDetails(v) => {
29                Self::from_encodable(ObjectId::ReadEventDetails_Encoding_DefaultBinary, &v)
30            }
31            HistoryReadAction::ReadRawModifiedDetails(v) => {
32                Self::from_encodable(ObjectId::ReadRawModifiedDetails_Encoding_DefaultBinary, &v)
33            }
34            HistoryReadAction::ReadProcessedDetails(v) => {
35                Self::from_encodable(ObjectId::ReadProcessedDetails_Encoding_DefaultBinary, &v)
36            }
37            HistoryReadAction::ReadAtTimeDetails(v) => {
38                Self::from_encodable(ObjectId::ReadAtTimeDetails_Encoding_DefaultBinary, &v)
39            }
40        }
41    }
42}
43
44/// Enumeration used with Session::history_update()
45pub enum HistoryUpdateAction {
46    UpdateDataDetails(UpdateDataDetails),
47    UpdateStructureDataDetails(UpdateStructureDataDetails),
48    UpdateEventDetails(UpdateEventDetails),
49    DeleteRawModifiedDetails(DeleteRawModifiedDetails),
50    DeleteAtTimeDetails(DeleteAtTimeDetails),
51    DeleteEventDetails(DeleteEventDetails),
52}
53
54impl From<&HistoryUpdateAction> for ExtensionObject {
55    fn from(action: &HistoryUpdateAction) -> Self {
56        match action {
57            HistoryUpdateAction::UpdateDataDetails(v) => {
58                Self::from_encodable(ObjectId::UpdateDataDetails_Encoding_DefaultBinary, v)
59            }
60            HistoryUpdateAction::UpdateStructureDataDetails(v) => Self::from_encodable(
61                ObjectId::UpdateStructureDataDetails_Encoding_DefaultBinary,
62                v,
63            ),
64            HistoryUpdateAction::UpdateEventDetails(v) => {
65                Self::from_encodable(ObjectId::UpdateEventDetails_Encoding_DefaultBinary, v)
66            }
67            HistoryUpdateAction::DeleteRawModifiedDetails(v) => {
68                Self::from_encodable(ObjectId::DeleteRawModifiedDetails_Encoding_DefaultBinary, v)
69            }
70            HistoryUpdateAction::DeleteAtTimeDetails(v) => {
71                Self::from_encodable(ObjectId::DeleteAtTimeDetails_Encoding_DefaultBinary, v)
72            }
73            HistoryUpdateAction::DeleteEventDetails(v) => {
74                Self::from_encodable(ObjectId::DeleteEventDetails_Encoding_DefaultBinary, v)
75            }
76        }
77    }
78}
79
80pub trait Service {
81    fn make_request_header(&self) -> RequestHeader;
82
83    /// Synchronously sends a request. The return value is the response to the request
84    fn send_request<T>(&self, request: T) -> Result<SupportedMessage, StatusCode>
85    where
86        T: Into<SupportedMessage>;
87
88    /// Asynchronously sends a request. The return value is the request handle of the request
89    fn async_send_request<T>(
90        &self,
91        request: T,
92        sender: Option<SyncSender<SupportedMessage>>,
93    ) -> Result<u32, StatusCode>
94    where
95        T: Into<SupportedMessage>;
96}
97
98/// Discovery Service set
99pub trait DiscoveryService: Service {
100    /// Sends a [`FindServersRequest`] to the server denoted by the discovery url.
101    ///
102    /// See OPC UA Part 4 - Services 5.4.2 for complete description of the service and error responses.
103    ///
104    /// # Arguments
105    ///
106    /// * `endpoint_url` - The network address that the Client used to access the Discovery Endpoint.
107    ///
108    /// # Returns
109    ///
110    /// * `Ok(Vec<ApplicationDescription>)` - A list of [`ApplicationDescription`] that meet criteria specified in the request.
111    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
112    ///
113    /// [`FindServersRequest`]: ./struct.FindServersRequest.html
114    /// [`ApplicationDescription`]: ./struct.ApplicationDescription.html
115    ///
116    fn find_servers<T>(&self, endpoint_url: T) -> Result<Vec<ApplicationDescription>, StatusCode>
117    where
118        T: Into<UAString>;
119
120    /// Obtain the list of endpoints supported by the server by sending it a [`GetEndpointsRequest`].
121    ///
122    /// See OPC UA Part 4 - Services 5.4.4 for complete description of the service and error responses.
123    ///
124    /// # Returns
125    ///
126    /// * `Ok(Vec<EndpointDescription>)` - A list of endpoints supported by the server
127    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
128    ///
129    /// [`GetEndpointsRequest`]: ./struct.GetEndpointsRequest.html
130    ///
131    fn get_endpoints(&self) -> Result<Vec<EndpointDescription>, StatusCode>;
132
133    /// This function is used by servers that wish to register themselves with a discovery server.
134    /// i.e. one server is the client to another server. The server sends a [`RegisterServerRequest`]
135    /// to the discovery server to register itself. Servers are expected to re-register themselves periodically
136    /// with the discovery server, with a maximum of 10 minute intervals.
137    ///
138    /// See OPC UA Part 4 - Services 5.4.5 for complete description of the service and error responses.
139    ///
140    /// # Arguments
141    ///
142    /// * `server` - The server to register
143    ///
144    /// # Returns
145    ///
146    /// * `Ok(())` - Success
147    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
148    ///
149    /// [`RegisterServerRequest`]: ./struct.RegisterServerRequest.html
150    ///
151    fn register_server(&self, server: RegisteredServer) -> Result<(), StatusCode>;
152}
153
154/// SecureChannel Service set
155pub trait SecureChannelService: Service {
156    /// Sends an [`OpenSecureChannelRequest`] to the server
157    ///
158    ///
159    /// See OPC UA Part 4 - Services 5.5.2 for complete description of the service and error responses.
160    /// # Returns
161    ///
162    /// * `Ok(())` - Success
163    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
164    ///
165    /// [`OpenSecureChannelRequest`]: ./struct.OpenSecureChannelRequest.html
166    ///
167    fn open_secure_channel(&self) -> Result<(), StatusCode>;
168
169    /// Sends a [`CloseSecureChannelRequest`] to the server which will cause the server to drop
170    /// the connection.
171    ///
172    /// See OPC UA Part 4 - Services 5.5.3 for complete description of the service and error responses.
173    ///
174    /// # Returns
175    ///
176    /// * `Ok(())` - Success
177    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
178    ///
179    /// [`CloseSecureChannelRequest`]: ./struct.CloseSecureChannelRequest.html
180    ///
181    fn close_secure_channel(&self) -> Result<(), StatusCode>;
182}
183
184/// Session Service set
185pub trait SessionService: Service {
186    /// Sends a [`CreateSessionRequest`] to the server, returning the session id of the created
187    /// session. Internally, the session will store the authentication token which is used for requests
188    /// subsequent to this call.
189    ///
190    /// See OPC UA Part 4 - Services 5.6.2 for complete description of the service and error responses.
191    ///
192    /// # Returns
193    ///
194    /// * `Ok(NodeId)` - Success, session id
195    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
196    ///
197    /// [`CreateSessionRequest`]: ./struct.CreateSessionRequest.html
198    ///
199    fn create_session(&self) -> Result<NodeId, StatusCode>;
200
201    /// Sends an [`ActivateSessionRequest`] to the server to activate this session
202    ///
203    /// See OPC UA Part 4 - Services 5.6.3 for complete description of the service and error responses.
204    ///
205    /// # Returns
206    ///
207    /// * `Ok(())` - Success
208    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
209    ///
210    /// [`ActivateSessionRequest`]: ./struct.ActivateSessionRequest.html
211    ///
212    fn activate_session(&self) -> Result<(), StatusCode>;
213
214    /// Cancels an outstanding service request by sending a [`CancelRequest`] to the server.
215    ///
216    /// See OPC UA Part 4 - Services 5.6.5 for complete description of the service and error responses.
217    ///
218    /// # Arguments
219    ///
220    /// * `request_handle` - Handle to the outstanding request to be cancelled.
221    ///
222    /// # Returns
223    ///
224    /// * `Ok(u32)` - Success, number of cancelled requests
225    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
226    ///
227    /// [`CancelRequest`]: ./struct.CancelRequest.html
228    ///
229    fn cancel(&self, request_handle: IntegerId) -> Result<u32, StatusCode>;
230}
231
232/// NodeManagement Service set
233
234pub trait NodeManagementService: Service {
235    /// Add nodes by sending a [`AddNodesRequest`] to the server.
236    ///
237    /// See OPC UA Part 4 - Services 5.7.2 for complete description of the service and error responses.
238    ///
239    /// # Arguments
240    ///
241    /// * `nodes_to_add` - A list of [`AddNodesItem`] to be added to the server.
242    ///
243    /// # Returns
244    ///
245    /// * `Ok(Vec<AddNodesResult>)` - A list of [`AddNodesResult`] corresponding to each add node operation.
246    /// * `Err(StatusCode)` - Status code reason for failure.
247    ///
248    /// [`AddNodesRequest`]: ./struct.AddNodesRequest.html
249    /// [`AddNodesItem`]: ./struct.AddNodesItem.html
250    /// [`AddNodesResult`]: ./struct.AddNodesResult.html
251    ///
252    fn add_nodes(&self, nodes_to_add: &[AddNodesItem]) -> Result<Vec<AddNodesResult>, StatusCode>;
253
254    /// Add references by sending a [`AddReferencesRequest`] to the server.
255    ///
256    /// See OPC UA Part 4 - Services 5.7.3 for complete description of the service and error responses.
257    ///
258    /// # Arguments
259    ///
260    /// * `references_to_add` - A list of [`AddReferencesItem`] to be sent to the server.
261    ///
262    /// # Returns
263    ///
264    /// * `Ok(Vec<StatusCode>)` - A list of `StatusCode` corresponding to each add reference operation.
265    /// * `Err(StatusCode)` - Status code reason for failure.
266    ///
267    /// [`AddReferencesRequest`]: ./struct.AddReferencesRequest.html
268    /// [`AddReferencesItem`]: ./struct.AddReferencesItem.html
269    ///
270    fn add_references(
271        &self,
272        references_to_add: &[AddReferencesItem],
273    ) -> Result<Vec<StatusCode>, StatusCode>;
274
275    /// Delete nodes by sending a [`DeleteNodesRequest`] to the server.
276    ///
277    /// See OPC UA Part 4 - Services 5.7.4 for complete description of the service and error responses.
278    ///
279    /// # Arguments
280    ///
281    /// * `nodes_to_delete` - A list of [`DeleteNodesItem`] to be sent to the server.
282    ///
283    /// # Returns
284    ///
285    /// * `Ok(Vec<StatusCode>)` - A list of `StatusCode` corresponding to each delete node operation.
286    /// * `Err(StatusCode)` - Status code reason for failure.
287    ///
288    /// [`DeleteNodesRequest`]: ./struct.DeleteNodesRequest.html
289    /// [`DeleteNodesItem`]: ./struct.DeleteNodesItem.html
290    ///
291    fn delete_nodes(
292        &self,
293        nodes_to_delete: &[DeleteNodesItem],
294    ) -> Result<Vec<StatusCode>, StatusCode>;
295
296    /// Delete references by sending a [`DeleteReferencesRequest`] to the server.
297    ///
298    /// See OPC UA Part 4 - Services 5.7.5 for complete description of the service and error responses.
299    ///
300    /// # Arguments
301    ///
302    /// * `nodes_to_delete` - A list of [`DeleteReferencesItem`] to be sent to the server.
303    ///
304    /// # Returns
305    ///
306    /// * `Ok(Vec<StatusCode>)` - A list of `StatusCode` corresponding to each delete node operation.
307    /// * `Err(StatusCode)` - Status code reason for failure.
308    ///
309    /// [`DeleteReferencesRequest`]: ./struct.DeleteReferencesRequest.html
310    /// [`DeleteReferencesItem`]: ./struct.DeleteReferencesItem.html
311    ///
312    fn delete_references(
313        &self,
314        references_to_delete: &[DeleteReferencesItem],
315    ) -> Result<Vec<StatusCode>, StatusCode>;
316}
317
318/// View Service set
319pub trait ViewService: Service {
320    /// Discover the references to the specified nodes by sending a [`BrowseRequest`] to the server.
321    ///
322    /// See OPC UA Part 4 - Services 5.8.2 for complete description of the service and error responses.
323    ///
324    /// # Arguments
325    ///
326    /// * `nodes_to_browse` - A list of [`BrowseDescription`] describing nodes to browse.
327    ///
328    /// # Returns
329    ///
330    /// * `Ok(Option<Vec<BrowseResult>)` - A list [`BrowseResult`] corresponding to each node to browse. A browse result
331    ///                                    may contain a continuation point, for use with `browse_next()`.
332    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
333    ///
334    /// [`BrowseRequest`]: ./struct.BrowseRequest.html
335    /// [`BrowseDescription`]: ./struct.BrowseDescription.html
336    /// [`BrowseResult`]: ./struct.BrowseResult.html
337    ///
338    fn browse(
339        &self,
340        nodes_to_browse: &[BrowseDescription],
341    ) -> Result<Option<Vec<BrowseResult>>, StatusCode>;
342
343    /// Continue to discover references to nodes by sending continuation points in a [`BrowseNextRequest`]
344    /// to the server. This function may have to be called repeatedly to process the initial query.
345    ///
346    /// See OPC UA Part 4 - Services 5.8.3 for complete description of the service and error responses.
347    ///
348    /// # Arguments
349    ///
350    /// * `release_continuation_points` - Flag indicating if the continuation points should be released by the server
351    /// * `continuation_points` - A list of [`BrowseDescription`] continuation points
352    ///
353    /// # Returns
354    ///
355    /// * `Ok(Option<Vec<BrowseResult>)` - A list [`BrowseResult`] corresponding to each node to browse. A browse result
356    ///                                    may contain a continuation point, for use with `browse_next()`.
357    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
358    ///
359    /// [`BrowseRequest`]: ./struct.BrowseRequest.html
360    /// [`BrowseNextRequest`]: ./struct.BrowseNextRequest.html
361    /// [`BrowseResult`]: ./struct.BrowseResult.html
362    ///
363    fn browse_next(
364        &self,
365        release_continuation_points: bool,
366        continuation_points: &[ByteString],
367    ) -> Result<Option<Vec<BrowseResult>>, StatusCode>;
368
369    /// Translate browse paths to NodeIds by sending a [`TranslateBrowsePathsToNodeIdsRequest`] request to the Server
370    /// Each [`BrowsePath`] is constructed of a starting node and a `RelativePath`. The specified starting node
371    /// identifies the node from which the RelativePath is based. The RelativePath contains a sequence of
372    /// ReferenceTypes and BrowseNames.
373    ///
374    /// See OPC UA Part 4 - Services 5.8.4 for complete description of the service and error responses.
375    ///
376    /// # Arguments
377    ///
378    /// * `browse_paths` - A list of [`BrowsePath`] node + relative path for the server to look up
379    ///
380    /// # Returns
381    ///
382    /// * `Ok(Vec<BrowsePathResult>>)` - List of [`BrowsePathResult`] for the list of browse
383    ///                       paths. The size and order of the list matches the size and order of the `browse_paths`
384    ///                       parameter.
385    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
386    ///
387    /// [`TranslateBrowsePathsToNodeIdsRequest`]: ./struct.TranslateBrowsePathsToNodeIdsRequest.html
388    /// [`BrowsePath`]: ./struct.BrowsePath.html
389    /// [`BrowsePathResult`]: ./struct.BrowsePathResult.html
390    fn translate_browse_paths_to_node_ids(
391        &self,
392        browse_paths: &[BrowsePath],
393    ) -> Result<Vec<BrowsePathResult>, StatusCode>;
394
395    /// Register nodes on the server by sending a [`RegisterNodesRequest`]. The purpose of this
396    /// call is server-dependent but allows a client to ask a server to create nodes which are
397    /// otherwise expensive to set up or maintain, e.g. nodes attached to hardware.
398    ///
399    /// See OPC UA Part 4 - Services 5.8.5 for complete description of the service and error responses.
400    ///
401    /// # Arguments
402    ///
403    /// * `nodes_to_register` - A list of [`NodeId`] nodes for the server to register
404    ///
405    /// # Returns
406    ///
407    /// * `Ok(Vec<NodeId>)` - A list of [`NodeId`] corresponding to size and order of the input. The
408    ///                       server may return an alias for the input `NodeId`
409    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
410    ///
411    /// [`RegisterNodesRequest`]: ./struct.RegisterNodesRequest.html
412    /// [`NodeId`]: ./struct.NodeId.html
413    fn register_nodes(&self, nodes_to_register: &[NodeId]) -> Result<Vec<NodeId>, StatusCode>;
414
415    /// Unregister nodes on the server by sending a [`UnregisterNodesRequest`]. This indicates to
416    /// the server that the client relinquishes any need for these nodes. The server will ignore
417    /// unregistered nodes.
418    ///
419    /// See OPC UA Part 4 - Services 5.8.5 for complete description of the service and error responses.
420    ///
421    /// # Arguments
422    ///
423    /// * `nodes_to_unregister` - A list of [`NodeId`] nodes for the server to unregister
424    ///
425    /// # Returns
426    ///
427    /// * `Ok(())` - Request succeeded, server ignores invalid nodes
428    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
429    ///
430    /// [`UnregisterNodesRequest`]: ./struct.UnregisterNodesRequest.html
431    /// [`NodeId`]: ./struct.NodeId.html
432    ///
433    fn unregister_nodes(&self, nodes_to_unregister: &[NodeId]) -> Result<(), StatusCode>;
434}
435
436/// Attribute Service set
437pub trait AttributeService: Service {
438    /// Reads the value of nodes by sending a [`ReadRequest`] to the server.
439    ///
440    /// See OPC UA Part 4 - Services 5.10.2 for complete description of the service and error responses.
441    ///
442    /// # Arguments
443    ///
444    /// * `nodes_to_read` - A list of [`ReadValueId`] to be read by the server.
445    /// * `timestamps_to_return` - The [`TimestampsToReturn`] for each node, Both, Server, Source or None
446    /// * `max_age` - The maximum age of value to read in milliseconds. Read the service description
447    ///               for details. Basically it will attempt to read a value within the age range or
448    ///               attempt to read a new value. If 0 the server will attempt to read a new value from the datasource.
449    ///               If set to `i32::MAX` or greater, the server shall attempt to get a cached value.
450    ///
451    /// # Returns
452    ///
453    /// * `Ok(Vec<DataValue>)` - A list of [`DataValue`] corresponding to each read operation.
454    /// * `Err(StatusCode)` - Status code reason for failure.
455    ///
456    /// [`ReadRequest`]: ./struct.ReadRequest.html
457    /// [`ReadValueId`]: ./struct.ReadValueId.html
458    /// [`DataValue`]: ./struct.DataValue.html
459    ///
460    fn read(
461        &self,
462        nodes_to_read: &[ReadValueId],
463        timestamps_to_return: TimestampsToReturn,
464        max_age: f64,
465    ) -> Result<Vec<DataValue>, StatusCode>;
466
467    /// Reads historical values or events of one or more nodes. The caller is expected to provide
468    /// a HistoryReadAction enum which must be one of the following:
469    ///
470    /// * HistoryReadAction::ReadEventDetails
471    /// * HistoryReadAction::ReadRawModifiedDetails
472    /// * HistoryReadAction::ReadProcessedDetails
473    /// * HistoryReadAction::ReadAtTimeDetails
474    ///
475    /// See OPC UA Part 4 - Services 5.10.3 for complete description of the service and error responses.
476    ///
477    /// # Arguments
478    ///
479    /// * `history_read_details` - A history read operation encoded in an `ExtensionObject`.
480    /// * `timestamps_to_return` - Enumeration of which timestamps to return.
481    /// * `release_continuation_points` - Flag indicating whether to release the continuation point for the operation.
482    /// * `nodes_to_read` - The list of `HistoryReadValueId` of the nodes to apply the history read operation to.
483    ///
484    /// # Returns
485    ///
486    /// * `Ok(Vec<HistoryReadResult>)` - A list of `HistoryReadResult` results corresponding to history read operation.
487    /// * `Err(StatusCode)` - Status code reason for failure.
488    ///
489    fn history_read(
490        &self,
491        history_read_details: HistoryReadAction,
492        timestamps_to_return: TimestampsToReturn,
493        release_continuation_points: bool,
494        nodes_to_read: &[HistoryReadValueId],
495    ) -> Result<Vec<HistoryReadResult>, StatusCode>;
496
497    /// Writes values to nodes by sending a [`WriteRequest`] to the server. Note that some servers may reject DataValues
498    /// containing source or server timestamps.
499    ///
500    /// See OPC UA Part 4 - Services 5.10.4 for complete description of the service and error responses.
501    ///
502    /// # Arguments
503    ///
504    /// * `nodes_to_write` - A list of [`WriteValue`] to be sent to the server.
505    ///
506    /// # Returns
507    ///
508    /// * `Ok(Vec<StatusCode>)` - A list of `StatusCode` results corresponding to each write operation.
509    /// * `Err(StatusCode)` - Status code reason for failure.
510    ///
511    /// [`WriteRequest`]: ./struct.WriteRequest.html
512    /// [`WriteValue`]: ./struct.WriteValue.html
513    ///
514    fn write(&self, nodes_to_write: &[WriteValue]) -> Result<Vec<StatusCode>, StatusCode>;
515
516    /// Updates historical values. The caller is expected to provide one or more history update operations
517    /// in a slice of HistoryUpdateAction enums which are one of the following:
518    ///
519    /// * UpdateDataDetails
520    /// * UpdateStructureDataDetails
521    /// * UpdateEventDetails
522    /// * DeleteRawModifiedDetails
523    /// * DeleteAtTimeDetails
524    /// * DeleteEventDetails
525    ///
526    /// See OPC UA Part 4 - Services 5.10.5 for complete description of the service and error responses.
527    ///
528    /// # Arguments
529    ///
530    /// * `history_update_details` - A list of history update operations each encoded as an `ExtensionObject`.
531    ///
532    /// # Returns
533    ///
534    /// * `Ok(Vec<ClientHistoryUpdateResult>)` - A list of `ClientHistoryUpdateResult` results corresponding to history update operation.
535    /// * `Err(StatusCode)` - Status code reason for failure.
536    ///
537    fn history_update(
538        &self,
539        history_update_details: &[HistoryUpdateAction],
540    ) -> Result<Vec<HistoryUpdateResult>, StatusCode>;
541}
542
543/// Method Service set
544pub trait MethodService: Service {
545    /// Calls a single method on an object on the server by sending a [`CallRequest`] to the server.
546    ///
547    /// See OPC UA Part 4 - Services 5.11.2 for complete description of the service and error responses.
548    ///
549    /// # Arguments
550    ///
551    /// * `method` - The method to call. Note this function takes anything that can be turned into
552    ///   a [`CallMethodRequest`] which includes a (`NodeId`, `NodeId`, `Option<Vec<Variant>>`)
553    ///   which refers to the object id, method id, and input arguments respectively.
554    ///
555    /// # Returns
556    ///
557    /// * `Ok(CallMethodResult)` - A `[CallMethodResult]` for the Method call.
558    /// * `Err(StatusCode)` - Status code reason for failure.
559    ///
560    /// [`CallRequest`]: ./struct.CallRequest.html
561    /// [`CallMethodRequest`]: ./struct.CallMethodRequest.html
562    /// [`CallMethodResult`]: ./struct.CallMethodResult.html
563    ///
564    fn call<T>(&self, method: T) -> Result<CallMethodResult, StatusCode>
565    where
566        T: Into<CallMethodRequest>;
567
568    /// Calls GetMonitoredItems via call_method(), putting a sane interface on the input / output.
569    ///
570    /// # Arguments
571    ///
572    /// * `subscription_id` - Server allocated identifier for the subscription to return monitored items for.
573    ///
574    /// # Returns
575    ///
576    /// * `Ok((Vec<u32>, Vec<u32>))` - Result for call, consisting a list of (monitored_item_id, client_handle)
577    /// * `Err(StatusCode)` - Status code reason for failure.
578    ///
579    fn call_get_monitored_items(
580        &self,
581        subscription_id: u32,
582    ) -> Result<(Vec<u32>, Vec<u32>), StatusCode> {
583        let args = Some(vec![Variant::from(subscription_id)]);
584        let object_id: NodeId = ObjectId::Server.into();
585        let method_id: NodeId = MethodId::Server_GetMonitoredItems.into();
586        let request: CallMethodRequest = (object_id, method_id, args).into();
587        let response = self.call(request)?;
588        if let Some(mut result) = response.output_arguments {
589            if result.len() == 2 {
590                let server_handles = <Vec<u32>>::try_from(&result.remove(0))
591                    .map_err(|_| StatusCode::BadUnexpectedError)?;
592                let client_handles = <Vec<u32>>::try_from(&result.remove(0))
593                    .map_err(|_| StatusCode::BadUnexpectedError)?;
594                Ok((server_handles, client_handles))
595            } else {
596                error!("Expected a result with 2 args and didn't get it.");
597                Err(StatusCode::BadUnexpectedError)
598            }
599        } else {
600            error!("Expected a result and didn't get it.");
601            Err(StatusCode::BadUnexpectedError)
602        }
603    }
604}
605
606////////////////////////////////////////////////////////////////////////////////////////////////
607// MonitoredItem Service set
608////////////////////////////////////////////////////////////////////////////////////////////////
609pub trait MonitoredItemService: Service {
610    /// Creates monitored items on a subscription by sending a [`CreateMonitoredItemsRequest`] to the server.
611    ///
612    /// See OPC UA Part 4 - Services 5.12.2 for complete description of the service and error responses.
613    ///
614    /// # Arguments
615    ///
616    /// * `subscription_id` - The Server-assigned identifier for the Subscription that will report Notifications for this MonitoredItem
617    /// * `timestamps_to_return` - An enumeration that specifies the timestamp Attributes to be transmitted for each MonitoredItem.
618    /// * `items_to_create` - A list of [`MonitoredItemCreateRequest`] to be created and assigned to the specified Subscription.
619    ///
620    /// # Returns
621    ///
622    /// * `Ok(Vec<MonitoredItemCreateResult>)` - A list of [`MonitoredItemCreateResult`] corresponding to the items to create.
623    ///    The size and order of the list matches the size and order of the `items_to_create` request parameter.
624    /// * `Err(StatusCode)` - Status code reason for failure
625    ///
626    /// [`CreateMonitoredItemsRequest`]: ./struct.CreateMonitoredItemsRequest.html
627    /// [`MonitoredItemCreateRequest`]: ./struct.MonitoredItemCreateRequest.html
628    /// [`MonitoredItemCreateResult`]: ./struct.MonitoredItemCreateResult.html
629    ///
630    fn create_monitored_items(
631        &self,
632        subscription_id: u32,
633        timestamps_to_return: TimestampsToReturn,
634        items_to_create: &[MonitoredItemCreateRequest],
635    ) -> Result<Vec<MonitoredItemCreateResult>, StatusCode>;
636
637    /// Modifies monitored items on a subscription by sending a [`ModifyMonitoredItemsRequest`] to the server.
638    ///
639    /// See OPC UA Part 4 - Services 5.12.3 for complete description of the service and error responses.
640    ///
641    /// # Arguments
642    ///
643    /// * `subscription_id` - The Server-assigned identifier for the Subscription that will report Notifications for this MonitoredItem.
644    /// * `timestamps_to_return` - An enumeration that specifies the timestamp Attributes to be transmitted for each MonitoredItem.
645    /// * `items_to_modify` - The list of [`MonitoredItemModifyRequest`] to modify.
646    ///
647    /// # Returns
648    ///
649    /// * `Ok(Vec<MonitoredItemModifyResult>)` - A list of [`MonitoredItemModifyResult`] corresponding to the MonitoredItems to modify.
650    ///    The size and order of the list matches the size and order of the `items_to_modify` request parameter.
651    /// * `Err(StatusCode)` - Status code reason for failure.
652    ///
653    /// [`ModifyMonitoredItemsRequest`]: ./struct.ModifyMonitoredItemsRequest.html
654    /// [`MonitoredItemModifyRequest`]: ./struct.MonitoredItemModifyRequest.html
655    /// [`MonitoredItemModifyResult`]: ./struct.MonitoredItemModifyResult.html
656    ///
657    fn modify_monitored_items(
658        &self,
659        subscription_id: u32,
660        timestamps_to_return: TimestampsToReturn,
661        items_to_modify: &[MonitoredItemModifyRequest],
662    ) -> Result<Vec<MonitoredItemModifyResult>, StatusCode>;
663
664    /// Sets the monitoring mode on one or more monitored items by sending a [`SetMonitoringModeRequest`]
665    /// to the server.
666    ///
667    /// See OPC UA Part 4 - Services 5.12.4 for complete description of the service and error responses.
668    ///
669    /// # Arguments
670    ///
671    /// * `subscription_id` - the subscription identifier containing the monitored items to be modified.
672    /// * `monitoring_mode` - the monitored mode to apply to the monitored items
673    /// * `monitored_item_ids` - the monitored items to be modified
674    ///
675    /// # Returns
676    ///
677    /// * `Ok(Vec<StatusCode>)` - Individual result for each monitored item.
678    /// * `Err(StatusCode)` - Status code reason for failure.
679    ///
680    /// [`SetMonitoringModeRequest`]: ./struct.SetMonitoringModeRequest.html
681    ///
682    fn set_monitoring_mode(
683        &self,
684        subscription_id: u32,
685        monitoring_mode: MonitoringMode,
686        monitored_item_ids: &[u32],
687    ) -> Result<Vec<StatusCode>, StatusCode>;
688
689    /// Sets a monitored item so it becomes the trigger that causes other monitored items to send
690    /// change events in the same update. Sends a [`SetTriggeringRequest`] to the server.
691    /// Note that `items_to_remove` is applied before `items_to_add`.
692    ///
693    /// See OPC UA Part 4 - Services 5.12.5 for complete description of the service and error responses.
694    ///
695    /// # Arguments
696    ///
697    /// * `subscription_id` - the subscription identifier containing the monitored item to be used as the trigger.
698    /// * `monitored_item_id` - the monitored item that is the trigger.
699    /// * `links_to_add` - zero or more items to be added to the monitored item's triggering list.
700    /// * `items_to_remove` - zero or more items to be removed from the monitored item's triggering list.
701    ///
702    /// # Returns
703    ///
704    /// * `Ok((Option<Vec<StatusCode>>, Option<Vec<StatusCode>>))` - Individual result for each item added / removed for the SetTriggering call.
705    /// * `Err(StatusCode)` - Status code reason for failure.
706    ///
707    /// [`SetTriggeringRequest`]: ./struct.SetTriggeringRequest.html
708    ///
709    fn set_triggering(
710        &self,
711        subscription_id: u32,
712        triggering_item_id: u32,
713        links_to_add: &[u32],
714        links_to_remove: &[u32],
715    ) -> Result<(Option<Vec<StatusCode>>, Option<Vec<StatusCode>>), StatusCode>;
716
717    /// Deletes monitored items from a subscription by sending a [`DeleteMonitoredItemsRequest`] to the server.
718    ///
719    /// See OPC UA Part 4 - Services 5.12.6 for complete description of the service and error responses.
720    ///
721    /// # Arguments
722    ///
723    /// * `subscription_id` - The Server-assigned identifier for the Subscription that will report Notifications for this MonitoredItem.
724    /// * `items_to_delete` - List of Server-assigned ids for the MonitoredItems to be deleted.
725    ///
726    /// # Returns
727    ///
728    /// * `Ok(Vec<StatusCode>)` - List of StatusCodes for the MonitoredItems to delete. The size and
729    ///   order of the list matches the size and order of the `items_to_delete` request parameter.
730    /// * `Err(StatusCode)` - Status code reason for failure.
731    ///
732    /// [`DeleteMonitoredItemsRequest`]: ./struct.DeleteMonitoredItemsRequest.html
733    ///
734    fn delete_monitored_items(
735        &self,
736        subscription_id: u32,
737        items_to_delete: &[u32],
738    ) -> Result<Vec<StatusCode>, StatusCode>;
739}
740
741////////////////////////////////////////////////////////////////////////////////////////////////
742// Subscription Service set
743////////////////////////////////////////////////////////////////////////////////////////////////
744pub trait SubscriptionService: Service {
745    /// Create a subscription by sending a [`CreateSubscriptionRequest`] to the server.
746    ///
747    /// See OPC UA Part 4 - Services 5.13.2 for complete description of the service and error responses.
748    ///
749    /// # Arguments
750    ///
751    /// * `publishing_interval` - The requested publishing interval defines the cyclic rate that
752    ///   the Subscription is being requested to return Notifications to the Client. This interval
753    ///   is expressed in milliseconds. This interval is represented by the publishing timer in the
754    ///   Subscription state table. The negotiated value for this parameter returned in the
755    ///   response is used as the default sampling interval for MonitoredItems assigned to this
756    ///   Subscription. If the requested value is 0 or negative, the server shall revise with the
757    ///   fastest supported publishing interval in milliseconds.
758    /// * `lifetime_count` - Requested lifetime count. The lifetime count shall be a minimum of
759    ///   three times the keep keep-alive count. When the publishing timer has expired this
760    ///   number of times without a Publish request being available to send a NotificationMessage,
761    ///   then the Subscription shall be deleted by the Server.
762    /// * `max_keep_alive_count` - Requested maximum keep-alive count. When the publishing timer has
763    ///   expired this number of times without requiring any NotificationMessage to be sent, the
764    ///   Subscription sends a keep-alive Message to the Client. The negotiated value for this
765    ///   parameter is returned in the response. If the requested value is 0, the server shall
766    ///   revise with the smallest supported keep-alive count.
767    /// * `max_notifications_per_publish` - The maximum number of notifications that the Client
768    ///   wishes to receive in a single Publish response. A value of zero indicates that there is
769    ///   no limit. The number of notifications per Publish is the sum of monitoredItems in
770    ///   the DataChangeNotification and events in the EventNotificationList.
771    /// * `priority` - Indicates the relative priority of the Subscription. When more than one
772    ///   Subscription needs to send Notifications, the Server should de-queue a Publish request
773    ///   to the Subscription with the highest priority number. For Subscriptions with equal
774    ///   priority the Server should de-queue Publish requests in a round-robin fashion.
775    ///   A Client that does not require special priority settings should set this value to zero.
776    /// * `publishing_enabled` - A boolean parameter with the following values - `true` publishing
777    ///   is enabled for the Subscription, `false`, publishing is disabled for the Subscription.
778    ///   The value of this parameter does not affect the value of the monitoring mode Attribute of
779    ///   MonitoredItems.
780    ///
781    /// # Returns
782    ///
783    /// * `Ok(u32)` - identifier for new subscription
784    /// * `Err(StatusCode)` - Status code reason for failure
785    ///
786    /// [`CreateSubscriptionRequest`]: ./struct.CreateSubscriptionRequest.html
787    ///
788    fn create_subscription<CB>(
789        &self,
790        publishing_interval: f64,
791        lifetime_count: u32,
792        max_keep_alive_count: u32,
793        max_notifications_per_publish: u32,
794        priority: u8,
795        publishing_enabled: bool,
796        callback: CB,
797    ) -> Result<u32, StatusCode>
798    where
799        CB: OnSubscriptionNotification + Send + Sync + 'static;
800
801    /// Modifies a subscription by sending a [`ModifySubscriptionRequest`] to the server.
802    ///
803    /// See OPC UA Part 4 - Services 5.13.3 for complete description of the service and error responses.
804    ///
805    /// # Arguments
806    ///
807    /// * `subscription_id` - subscription identifier returned from `create_subscription`.
808    ///
809    /// See `create_subscription` for description of other parameters
810    ///
811    /// # Returns
812    ///
813    /// * `Ok(())` - Success
814    /// * `Err(StatusCode)` - Request failed, status code is the reason for failure
815    ///
816    /// [`ModifySubscriptionRequest`]: ./struct.ModifySubscriptionRequest.html
817    ///
818    fn modify_subscription(
819        &self,
820        subscription_id: u32,
821        publishing_interval: f64,
822        lifetime_count: u32,
823        max_keep_alive_count: u32,
824        max_notifications_per_publish: u32,
825        priority: u8,
826    ) -> Result<(), StatusCode>;
827
828    /// Changes the publishing mode of subscriptions by sending a [`SetPublishingModeRequest`] to the server.
829    ///
830    /// See OPC UA Part 4 - Services 5.13.4 for complete description of the service and error responses.
831    ///
832    /// # Arguments
833    ///
834    /// * `subscription_ids` - one or more subscription identifiers.
835    /// * `publishing_enabled` - A boolean parameter with the following values - `true` publishing
836    ///   is enabled for the Subscriptions, `false`, publishing is disabled for the Subscriptions.
837    ///
838    /// # Returns
839    ///
840    /// * `Ok(Vec<StatusCode>)` - Service return code for the  action for each id, `Good` or `BadSubscriptionIdInvalid`
841    /// * `Err(StatusCode)` - Status code reason for failure
842    ///
843    /// [`SetPublishingModeRequest`]: ./struct.SetPublishingModeRequest.html
844    ///
845    fn set_publishing_mode(
846        &self,
847        subscription_ids: &[u32],
848        publishing_enabled: bool,
849    ) -> Result<Vec<StatusCode>, StatusCode>;
850
851    /// Transfers Subscriptions and their MonitoredItems from one Session to another. For example,
852    /// a Client may need to reopen a Session and then transfer its Subscriptions to that Session.
853    /// It may also be used by one Client to take over a Subscription from another Client by
854    /// transferring the Subscription to its Session.
855    ///
856    /// See OPC UA Part 4 - Services 5.13.7 for complete description of the service and error responses.
857    ///
858    /// * `subscription_ids` - one or more subscription identifiers.
859    /// * `send_initial_values` - A boolean parameter with the following values - `true` the first
860    ///   publish response shall contain the current values of all monitored items in the subscription,
861    ///   `false`, the first publish response shall contain only the value changes since the last
862    ///   publish response was sent.
863    ///
864    /// # Returns
865    ///
866    /// * `Ok(Vec<TransferResult>)` - The [`TransferResult`] for each transfer subscription.
867    /// * `Err(StatusCode)` - Status code reason for failure
868    ///
869    /// [`TransferSubscriptionsRequest`]: ./struct.TransferSubscriptionsRequest.html
870    /// [`TransferResult`]: ./struct.TransferResult.html
871    ///
872    fn transfer_subscriptions(
873        &self,
874        subscription_ids: &[u32],
875        send_initial_values: bool,
876    ) -> Result<Vec<TransferResult>, StatusCode>;
877
878    /// Deletes a subscription by sending a [`DeleteSubscriptionsRequest`] to the server.
879    ///
880    /// See OPC UA Part 4 - Services 5.13.8 for complete description of the service and error responses.
881    ///
882    /// # Arguments
883    ///
884    /// * `subscription_id` - subscription identifier returned from `create_subscription`.
885    ///
886    /// # Returns
887    ///
888    /// * `Ok(StatusCode)` - Service return code for the delete action, `Good` or `BadSubscriptionIdInvalid`
889    /// * `Err(StatusCode)` - Status code reason for failure
890    ///
891    /// [`DeleteSubscriptionsRequest`]: ./struct.DeleteSubscriptionsRequest.html
892    ///
893    fn delete_subscription(&self, subscription_id: u32) -> Result<StatusCode, StatusCode>;
894
895    /// Deletes subscriptions by sending a [`DeleteSubscriptionsRequest`] to the server with the list
896    /// of subscriptions to delete.
897    ///
898    /// See OPC UA Part 4 - Services 5.13.8 for complete description of the service and error responses.
899    ///
900    /// # Arguments
901    ///
902    /// * `subscription_ids` - List of subscription identifiers to delete.
903    ///
904    /// # Returns
905    ///
906    /// * `Ok(Vec<StatusCode>)` - List of result for delete action on each id, `Good` or `BadSubscriptionIdInvalid`
907    ///   The size and order of the list matches the size and order of the input.
908    /// * `Err(StatusCode)` - Status code reason for failure
909    ///
910    /// [`DeleteSubscriptionsRequest`]: ./struct.DeleteSubscriptionsRequest.html
911    ///
912    fn delete_subscriptions(&self, subscription_ids: &[u32])
913        -> Result<Vec<StatusCode>, StatusCode>;
914}