Skip to main content

opcua_client/session/services/subscriptions/
service.rs

1use std::{
2    collections::HashSet,
3    time::{Duration, Instant},
4};
5
6use crate::{
7    session::{
8        process_service_result, process_unexpected_response,
9        request_builder::{builder_base, builder_debug, builder_error, RequestHeaderBuilder},
10        services::subscriptions::{
11            callbacks::OnSubscriptionNotificationCore, ModifyMonitoredItem,
12            PreInsertMonitoredItems, Subscription,
13        },
14        session_debug, session_error, session_warn,
15    },
16    Session, UARequest,
17};
18use opcua_core::{handle::AtomicHandle, sync::Mutex, trace_lock, ResponseMessage};
19use opcua_types::{
20    AttributeId, CreateMonitoredItemsRequest, CreateSubscriptionRequest,
21    CreateSubscriptionResponse, DeleteMonitoredItemsRequest, DeleteMonitoredItemsResponse,
22    DeleteSubscriptionsRequest, DeleteSubscriptionsResponse, DiagnosticInfo, Error,
23    ExtensionObject, IntegerId, ModifyMonitoredItemsRequest, ModifyMonitoredItemsResponse,
24    ModifySubscriptionRequest, ModifySubscriptionResponse, MonitoredItemCreateRequest,
25    MonitoredItemCreateResult, MonitoredItemModifyRequest, MonitoredItemModifyResult,
26    MonitoringMode, MonitoringParameters, NodeId, NotificationMessage, PublishRequest,
27    PublishResponse, ReadValueId, RepublishRequest, RepublishResponse, ResponseHeader,
28    SetMonitoringModeRequest, SetMonitoringModeResponse, SetPublishingModeRequest,
29    SetPublishingModeResponse, SetTriggeringRequest, SetTriggeringResponse, StatusCode,
30    SubscriptionAcknowledgement, TimestampsToReturn, TransferResult, TransferSubscriptionsRequest,
31    TransferSubscriptionsResponse,
32};
33use tracing::{debug_span, enabled, Instrument};
34
35use super::state::SubscriptionState;
36
37/// Create a subscription by sending a [`CreateSubscriptionRequest`] to the server.
38///
39/// See OPC UA Part 4 - Services 5.13.2 for complete description of the service and error responses.
40pub struct CreateSubscription {
41    publishing_interval: Duration,
42    lifetime_count: u32,
43    keep_alive_count: u32,
44    max_notifications_per_publish: u32,
45    publishing_enabled: bool,
46    priority: u8,
47
48    header: RequestHeaderBuilder,
49}
50
51builder_base!(CreateSubscription);
52
53impl CreateSubscription {
54    /// Construct a new call to the `CreateSubscription` service.
55    pub fn new(session: &Session) -> Self {
56        Self {
57            publishing_interval: Duration::from_millis(500),
58            lifetime_count: 60,
59            keep_alive_count: 20,
60            max_notifications_per_publish: 0,
61            publishing_enabled: true,
62            priority: 0,
63            header: RequestHeaderBuilder::new_from_session(session),
64        }
65    }
66
67    /// Construct a new call to the `CreateSubscription` service, setting header parameters manually.
68    pub fn new_manual(
69        session_id: u32,
70        timeout: Duration,
71        auth_token: NodeId,
72        request_handle: IntegerId,
73    ) -> Self {
74        Self {
75            publishing_interval: Duration::from_millis(500),
76            lifetime_count: 60,
77            keep_alive_count: 20,
78            max_notifications_per_publish: 0,
79            publishing_enabled: true,
80            priority: 0,
81            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
82        }
83    }
84
85    /// The requested publishing interval defines the cyclic rate that
86    /// the Subscription is being requested to return Notifications to the Client. This interval
87    /// is expressed in milliseconds. This interval is represented by the publishing timer in the
88    /// Subscription state table. The negotiated value for this parameter returned in the
89    /// response is used as the default sampling interval for MonitoredItems assigned to this
90    /// Subscription. If the requested value is 0 or negative, the server shall revise with the
91    /// fastest supported publishing interval in milliseconds.
92    pub fn publishing_interval(mut self, interval: Duration) -> Self {
93        self.publishing_interval = interval;
94        self
95    }
96
97    /// Requested lifetime count. The lifetime count shall be a minimum of
98    /// three times the keep keep-alive count. When the publishing timer has expired this
99    /// number of times without a Publish request being available to send a NotificationMessage,
100    /// then the Subscription shall be deleted by the Server.
101    pub fn max_lifetime_count(mut self, lifetime_count: u32) -> Self {
102        self.lifetime_count = lifetime_count;
103        self
104    }
105
106    /// Requested maximum keep-alive count. When the publishing timer has
107    /// expired this number of times without requiring any NotificationMessage to be sent, the
108    /// Subscription sends a keep-alive Message to the Client. The negotiated value for this
109    /// parameter is returned in the response. If the requested value is 0, the server shall
110    /// revise with the smallest supported keep-alive count.
111    pub fn max_keep_alive_count(mut self, keep_alive_count: u32) -> Self {
112        self.keep_alive_count = keep_alive_count;
113        self
114    }
115
116    /// The maximum number of notifications that the Client
117    /// wishes to receive in a single Publish response. A value of zero indicates that there is
118    /// no limit. The number of notifications per Publish is the sum of monitoredItems in
119    /// the DataChangeNotification and events in the EventNotificationList.
120    pub fn max_notifications_per_publish(mut self, max_notifications_per_publish: u32) -> Self {
121        self.max_notifications_per_publish = max_notifications_per_publish;
122        self
123    }
124
125    /// Indicates the relative priority of the Subscription. When more than one
126    /// Subscription needs to send Notifications, the Server should de-queue a Publish request
127    /// to the Subscription with the highest priority number. For Subscriptions with equal
128    /// priority the Server should de-queue Publish requests in a round-robin fashion.
129    pub fn priority(mut self, priority: u8) -> Self {
130        self.priority = priority;
131        self
132    }
133
134    /// A boolean parameter with the following values - `true` publishing
135    /// is enabled for the Subscription, `false`, publishing is disabled for the Subscription.
136    /// The value of this parameter does not affect the value of the monitoring mode Attribute of
137    /// MonitoredItems.
138    pub fn publishing_enabled(mut self, publishing_enabled: bool) -> Self {
139        self.publishing_enabled = publishing_enabled;
140        self
141    }
142}
143
144impl UARequest for CreateSubscription {
145    type Out = CreateSubscriptionResponse;
146
147    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
148    where
149        Self: 'a,
150    {
151        let request = CreateSubscriptionRequest {
152            request_header: self.header.header,
153            requested_publishing_interval: self.publishing_interval.as_millis() as f64,
154            requested_lifetime_count: self.lifetime_count,
155            requested_max_keep_alive_count: self.keep_alive_count,
156            max_notifications_per_publish: self.max_notifications_per_publish,
157            publishing_enabled: self.publishing_enabled,
158            priority: self.priority,
159        };
160        let span = debug_span!(
161            "Sending CreateSubscription request",
162            publishing_interval_ms = self.publishing_interval.as_millis(),
163            lifetime_count = self.lifetime_count,
164            keep_alive_count = self.keep_alive_count,
165            max_notifications_per_publish = self.max_notifications_per_publish,
166            publishing_enabled = self.publishing_enabled,
167            priority = self.priority
168        );
169
170        let response = channel
171            .send(request, self.header.timeout)
172            .instrument(span.clone())
173            .await?;
174
175        let _h = span.enter();
176        if let ResponseMessage::CreateSubscription(response) = response {
177            process_service_result(&response.response_header)?;
178            builder_debug!(
179                self,
180                "create_subscription, created a subscription with id {}",
181                response.subscription_id
182            );
183            Ok(*response)
184        } else {
185            builder_error!(self, "create_subscription failed {:?}", response);
186            Err(process_unexpected_response(response))
187        }
188    }
189}
190
191/// Modifies a subscription by sending a [`ModifySubscriptionRequest`] to the server.
192///
193/// See OPC UA Part 4 - Services 5.13.3 for complete description of the service and error responses.
194#[derive(Clone)]
195pub struct ModifySubscription {
196    subscription_id: u32,
197    publishing_interval: Duration,
198    lifetime_count: u32,
199    keep_alive_count: u32,
200    max_notifications_per_publish: u32,
201    priority: u8,
202
203    header: RequestHeaderBuilder,
204}
205
206builder_base!(ModifySubscription);
207
208impl ModifySubscription {
209    /// Construct a new call to the `ModifySubscription` service.
210    pub fn new(subscription_id: u32, session: &Session) -> Self {
211        Self {
212            subscription_id,
213            publishing_interval: Duration::from_millis(500),
214            lifetime_count: 60,
215            keep_alive_count: 20,
216            max_notifications_per_publish: 0,
217            priority: 0,
218            header: RequestHeaderBuilder::new_from_session(session),
219        }
220    }
221
222    /// Construct a new call to the `ModifySubscription` service, setting header parameters manually.
223    pub fn new_manual(
224        subscription_id: u32,
225        session_id: u32,
226        timeout: Duration,
227        auth_token: NodeId,
228        request_handle: IntegerId,
229    ) -> Self {
230        Self {
231            subscription_id,
232            publishing_interval: Duration::from_millis(500),
233            lifetime_count: 60,
234            keep_alive_count: 20,
235            max_notifications_per_publish: 0,
236            priority: 0,
237            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
238        }
239    }
240
241    /// The requested publishing interval defines the cyclic rate that
242    /// the Subscription is being requested to return Notifications to the Client. This interval
243    /// is expressed in milliseconds. This interval is represented by the publishing timer in the
244    /// Subscription state table. The negotiated value for this parameter returned in the
245    /// response is used as the default sampling interval for MonitoredItems assigned to this
246    /// Subscription. If the requested value is 0 or negative, the server shall revise with the
247    /// fastest supported publishing interval in milliseconds.
248    pub fn publishing_interval(mut self, interval: Duration) -> Self {
249        self.publishing_interval = interval;
250        self
251    }
252
253    /// Requested lifetime count. The lifetime count shall be a minimum of
254    /// three times the keep keep-alive count. When the publishing timer has expired this
255    /// number of times without a Publish request being available to send a NotificationMessage,
256    /// then the Subscription shall be deleted by the Server.
257    pub fn max_lifetime_count(mut self, lifetime_count: u32) -> Self {
258        self.lifetime_count = lifetime_count;
259        self
260    }
261
262    /// Requested maximum keep-alive count. When the publishing timer has
263    /// expired this number of times without requiring any NotificationMessage to be sent, the
264    /// Subscription sends a keep-alive Message to the Client. The negotiated value for this
265    /// parameter is returned in the response. If the requested value is 0, the server shall
266    /// revise with the smallest supported keep-alive count.
267    pub fn max_keep_alive_count(mut self, keep_alive_count: u32) -> Self {
268        self.keep_alive_count = keep_alive_count;
269        self
270    }
271
272    /// The maximum number of notifications that the Client
273    /// wishes to receive in a single Publish response. A value of zero indicates that there is
274    /// no limit. The number of notifications per Publish is the sum of monitoredItems in
275    /// the DataChangeNotification and events in the EventNotificationList.
276    pub fn max_notifications_per_publish(mut self, max_notifications_per_publish: u32) -> Self {
277        self.max_notifications_per_publish = max_notifications_per_publish;
278        self
279    }
280
281    /// Indicates the relative priority of the Subscription. When more than one
282    /// Subscription needs to send Notifications, the Server should de-queue a Publish request
283    /// to the Subscription with the highest priority number. For Subscriptions with equal
284    /// priority the Server should de-queue Publish requests in a round-robin fashion.
285    pub fn priority(mut self, priority: u8) -> Self {
286        self.priority = priority;
287        self
288    }
289}
290
291impl UARequest for ModifySubscription {
292    type Out = ModifySubscriptionResponse;
293
294    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
295    where
296        Self: 'a,
297    {
298        let span = debug_span!(
299            "Sending ModifySubscription request",
300            subscription_id = self.subscription_id,
301            publishing_interval_ms = self.publishing_interval.as_millis(),
302            lifetime_count = self.lifetime_count,
303            keep_alive_count = self.keep_alive_count,
304            max_notifications_per_publish = self.max_notifications_per_publish,
305            priority = self.priority
306        );
307        let request = {
308            let _h = span.enter();
309            if self.subscription_id == 0 {
310                builder_error!(
311                    self,
312                    "modify_subscription, subscription id must be non-zero"
313                );
314                return Err(Error::new(
315                    StatusCode::BadInvalidArgument,
316                    "modify_subscription, subscription id must be non-zero",
317                ));
318            }
319
320            ModifySubscriptionRequest {
321                request_header: self.header.header,
322                subscription_id: self.subscription_id,
323                requested_publishing_interval: self.publishing_interval.as_millis() as f64,
324                requested_lifetime_count: self.lifetime_count,
325                requested_max_keep_alive_count: self.keep_alive_count,
326                max_notifications_per_publish: self.max_notifications_per_publish,
327                priority: self.priority,
328            }
329        };
330
331        let response = channel
332            .send(request, self.header.timeout)
333            .instrument(span.clone())
334            .await?;
335
336        let _h = span.enter();
337        if let ResponseMessage::ModifySubscription(response) = response {
338            process_service_result(&response.response_header)?;
339            builder_debug!(
340                self,
341                "modify_subscription success for {}",
342                self.subscription_id
343            );
344            Ok(*response)
345        } else {
346            builder_debug!(self, "modify_subscription failed");
347            Err(process_unexpected_response(response))
348        }
349    }
350}
351
352/// Changes the publishing mode of subscriptions by sending a [`SetPublishingModeRequest`] to the server.
353///
354/// See OPC UA Part 4 - Services 5.13.4 for complete description of the service and error responses.
355#[derive(Clone)]
356pub struct SetPublishingMode {
357    subscription_ids: Vec<u32>,
358    publishing_enabled: bool,
359
360    header: RequestHeaderBuilder,
361}
362
363builder_base!(SetPublishingMode);
364
365impl SetPublishingMode {
366    /// Construct a new call to the `SetPublishingMode` service.
367    pub fn new(publishing_enabled: bool, session: &Session) -> Self {
368        Self {
369            subscription_ids: Vec::new(),
370            publishing_enabled,
371            header: RequestHeaderBuilder::new_from_session(session),
372        }
373    }
374
375    /// Construct a new call to the `SetPublishingMode` service, setting header parameters manually.
376    pub fn new_manual(
377        publishing_enabled: bool,
378        session_id: u32,
379        timeout: Duration,
380        auth_token: NodeId,
381        request_handle: IntegerId,
382    ) -> Self {
383        Self {
384            subscription_ids: Vec::new(),
385            publishing_enabled,
386            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
387        }
388    }
389
390    /// Set the subscription IDs to update, overwriting any that were added previously.
391    pub fn subscription_ids(mut self, subscription_ids: Vec<u32>) -> Self {
392        self.subscription_ids = subscription_ids;
393        self
394    }
395
396    /// Add a subscription ID to update.
397    pub fn subscription(mut self, subscription_id: u32) -> Self {
398        self.subscription_ids.push(subscription_id);
399        self
400    }
401}
402
403impl UARequest for SetPublishingMode {
404    type Out = SetPublishingModeResponse;
405
406    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
407    where
408        Self: 'a,
409    {
410        let span = debug_span!(
411            "Sending SetPublishingMode request",
412             subscription_ids = ?self.subscription_ids,
413             publishing_enabled = self.publishing_enabled
414        );
415        let request = {
416            let _h = span.enter();
417            if self.subscription_ids.is_empty() {
418                builder_error!(
419                    self,
420                    "set_publishing_mode, no subscription ids were provided"
421                );
422                return Err(Error::new(
423                    StatusCode::BadNothingToDo,
424                    "set_publishing_mode, no subscription ids were provided",
425                ));
426            }
427
428            SetPublishingModeRequest {
429                request_header: self.header.header,
430                publishing_enabled: self.publishing_enabled,
431                subscription_ids: Some(self.subscription_ids.clone()),
432            }
433        };
434
435        let response = channel
436            .send(request, self.header.timeout)
437            .instrument(span.clone())
438            .await?;
439        let _h = span.enter();
440        if let ResponseMessage::SetPublishingMode(response) = response {
441            process_service_result(&response.response_header)?;
442            let num_results = response
443                .results
444                .as_ref()
445                .map(|l| l.len())
446                .unwrap_or_default();
447
448            if num_results != self.subscription_ids.len() {
449                builder_error!(
450                    self,
451                    "set_publishing_mode returned an incorrect number of results. Expected {}, got {}",
452                    self.subscription_ids.len(),
453                    num_results
454                );
455                return Err(Error::new(StatusCode::BadUnexpectedError, format!("set_publishing_mode returned an incorrect number of results. Expected {}, got {}",
456                    self.subscription_ids.len(),
457                    num_results)
458                ));
459            }
460
461            builder_debug!(self, "set_publishing_mode success");
462            Ok(*response)
463        } else {
464            builder_error!(self, "set_publishing_mode failed {:?}", response);
465            Err(process_unexpected_response(response))
466        }
467    }
468}
469
470#[derive(Clone)]
471/// Send a [`PublishRequest`] to the server to receive notifications from subscriptions.
472///
473/// See OPC UA Part 4 - Services 5.13.5 for complete description of the service and error responses.
474pub struct Publish {
475    header: RequestHeaderBuilder,
476    acks: Vec<SubscriptionAcknowledgement>,
477}
478
479builder_base!(Publish);
480
481impl Publish {
482    /// Construct a new call to the `Publish` service.
483    pub fn new(session: &Session) -> Self {
484        Self {
485            header: RequestHeaderBuilder::new_from_session(session),
486            acks: Vec::new(),
487        }
488        .timeout(session.publish_timeout)
489    }
490
491    /// Construct a new call to the `Publish` service, setting header parameters manually.
492    pub fn new_manual(
493        session_id: u32,
494        timeout: Duration,
495        auth_token: NodeId,
496        request_handle: IntegerId,
497    ) -> Self {
498        Self {
499            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
500            acks: Vec::new(),
501        }
502    }
503
504    /// Set the subscription acknowledgements to send, overwriting any that were added previously.
505    pub fn acks(mut self, acks: Vec<SubscriptionAcknowledgement>) -> Self {
506        self.acks = acks;
507        self
508    }
509
510    /// Add a subscription acknowledgement to send.
511    pub fn ack(mut self, subscription_id: u32, sequence_number: u32) -> Self {
512        self.acks.push(SubscriptionAcknowledgement {
513            subscription_id,
514            sequence_number,
515        });
516        self
517    }
518}
519
520impl UARequest for Publish {
521    type Out = PublishResponse;
522
523    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
524    where
525        Self: 'a,
526    {
527        let span = debug_span!(
528            "Sending Publish request",
529            num_acks = self.acks.len(),
530            timeout_ms = self.header.timeout.as_millis()
531        );
532        let request = {
533            let _h = span.enter();
534            if enabled!(tracing::Level::DEBUG) {
535                let sequence_nrs: Vec<u32> =
536                    self.acks.iter().map(|ack| ack.sequence_number).collect();
537                builder_debug!(
538                    self,
539                    "publish, acknowledging subscription acknowledgements with sequence nrs {:?}",
540                    sequence_nrs
541                );
542            }
543            PublishRequest {
544                request_header: self.header.header,
545                subscription_acknowledgements: if self.acks.is_empty() {
546                    None
547                } else {
548                    Some(self.acks.clone())
549                },
550            }
551        };
552
553        let response = channel
554            .send(request, self.header.timeout)
555            .instrument(span.clone())
556            .await?;
557        let _h = span.enter();
558        if let ResponseMessage::Publish(response) = response {
559            process_service_result(&response.response_header)?;
560            builder_debug!(self, "publish success");
561            Ok(*response)
562        } else {
563            builder_error!(self, "publish failed {:?}", response);
564            Err(process_unexpected_response(response))
565        }
566    }
567}
568
569/// Republishes notifications from a subscription by sending a [`RepublishRequest`] to the server.
570///
571/// See OPC UA Part 4 - Services 5.13.6 for complete description of the service and error responses.
572pub struct Republish {
573    subscription_id: u32,
574    retransmit_sequence_number: u32,
575
576    header: RequestHeaderBuilder,
577}
578
579builder_base!(Republish);
580
581impl Republish {
582    /// Construct a new call to the `Republish` service.
583    pub fn new(subscription_id: u32, retransmit_sequence_number: u32, session: &Session) -> Self {
584        Self {
585            subscription_id,
586            retransmit_sequence_number,
587            header: RequestHeaderBuilder::new_from_session(session),
588        }
589    }
590
591    /// Construct a new call to the `Republish` service, setting header parameters manually.
592    pub fn new_manual(
593        subscription_id: u32,
594        retransmit_sequence_number: u32,
595        session_id: u32,
596        timeout: Duration,
597        auth_token: NodeId,
598        request_handle: IntegerId,
599    ) -> Self {
600        Self {
601            subscription_id,
602            retransmit_sequence_number,
603            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
604        }
605    }
606}
607
608impl UARequest for Republish {
609    type Out = RepublishResponse;
610    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
611    where
612        Self: 'a,
613    {
614        let request = RepublishRequest {
615            request_header: self.header.header,
616            subscription_id: self.subscription_id,
617            retransmit_sequence_number: self.retransmit_sequence_number,
618        };
619        let span = debug_span!(
620            "Sending Republish request",
621            subscription_id = self.subscription_id,
622            retransmit_sequence_number = self.retransmit_sequence_number
623        );
624
625        let response = channel
626            .send(request, self.header.timeout)
627            .instrument(span.clone())
628            .await?;
629
630        let _h = span.enter();
631        if let ResponseMessage::Republish(response) = response {
632            process_service_result(&response.response_header)?;
633            builder_debug!(self, "republish success");
634            Ok(*response)
635        } else {
636            builder_error!(self, "republish failed {:?}", response);
637            Err(process_unexpected_response(response))
638        }
639    }
640}
641
642#[derive(Clone)]
643/// Transfers Subscriptions and their MonitoredItems from one Session to another. For example,
644/// a Client may need to reopen a Session and then transfer its Subscriptions to that Session.
645/// It may also be used by one Client to take over a Subscription from another Client by
646/// transferring the Subscription to its Session.
647///
648/// Note that if you call this manually, you will need to register the
649/// subscriptions in the subscription state ([`Session::subscription_state`]) in order to
650/// receive notifications.
651///
652/// See OPC UA Part 4 - Services 5.13.7 for complete description of the service and error responses.
653///
654pub struct TransferSubscriptions {
655    subscription_ids: Vec<u32>,
656    send_initial_values: bool,
657
658    header: RequestHeaderBuilder,
659}
660
661builder_base!(TransferSubscriptions);
662
663impl TransferSubscriptions {
664    /// Construct a new call to the `TransferSubscriptions` service.
665    pub fn new(session: &Session) -> Self {
666        Self {
667            subscription_ids: Vec::new(),
668            send_initial_values: false,
669            header: RequestHeaderBuilder::new_from_session(session),
670        }
671    }
672
673    /// Construct a new call to the `TransferSubscriptions` service, setting header parameters manually.
674    pub fn new_manual(
675        session_id: u32,
676        timeout: Duration,
677        auth_token: NodeId,
678        request_handle: IntegerId,
679    ) -> Self {
680        Self {
681            subscription_ids: Vec::new(),
682            send_initial_values: false,
683            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
684        }
685    }
686    /// A boolean parameter with the following values - `true` the first
687    /// publish response shall contain the current values of all monitored items in the subscription,
688    /// `false`, the first publish response shall contain only the value changes since the last
689    /// publish response was sent.
690    pub fn send_initial_values(mut self, send_initial_values: bool) -> Self {
691        self.send_initial_values = send_initial_values;
692        self
693    }
694
695    /// Set the subscription IDs to transfer, overwriting any that were added previously.
696    pub fn subscription_ids(mut self, subscription_ids: Vec<u32>) -> Self {
697        self.subscription_ids = subscription_ids;
698        self
699    }
700
701    /// Add a subscription ID to transfer.
702    pub fn subscription(mut self, subscription_id: u32) -> Self {
703        self.subscription_ids.push(subscription_id);
704        self
705    }
706}
707
708impl UARequest for TransferSubscriptions {
709    type Out = TransferSubscriptionsResponse;
710
711    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
712    where
713        Self: 'a,
714    {
715        let span = debug_span!(
716            "Sending TransferSubscriptions request",
717            subscription_ids = ?self.subscription_ids,
718            send_initial_values = self.send_initial_values
719        );
720        let request = {
721            let _h = span.enter();
722            if self.subscription_ids.is_empty() {
723                builder_error!(
724                    self,
725                    "transfer_subscriptions, no subscription ids were provided"
726                );
727                return Err(Error::new(
728                    StatusCode::BadNothingToDo,
729                    "transfer_subscriptions, no subscription ids were provided",
730                ));
731            }
732            TransferSubscriptionsRequest {
733                request_header: self.header.header,
734                subscription_ids: Some(self.subscription_ids),
735                send_initial_values: self.send_initial_values,
736            }
737        };
738        let response = channel
739            .send(request, self.header.timeout)
740            .instrument(span.clone())
741            .await?;
742        let _h = span.enter();
743        if let ResponseMessage::TransferSubscriptions(response) = response {
744            process_service_result(&response.response_header)?;
745            builder_debug!(self, "transfer_subscriptions success");
746            Ok(*response)
747        } else {
748            builder_error!(self, "transfer_subscriptions failed {:?}", response);
749            Err(process_unexpected_response(response))
750        }
751    }
752}
753
754#[derive(Clone)]
755/// Deletes subscriptions by sending a [`DeleteSubscriptionsRequest`] to the server with the list
756/// of subscriptions to delete.
757///
758/// See OPC UA Part 4 - Services 5.13.8 for complete description of the service and error responses.
759pub struct DeleteSubscriptions {
760    subscription_ids: Vec<u32>,
761
762    header: RequestHeaderBuilder,
763}
764
765builder_base!(DeleteSubscriptions);
766
767impl DeleteSubscriptions {
768    /// Construct a new call to the `DeleteSubscriptions` service.
769    pub fn new(session: &Session) -> Self {
770        Self {
771            subscription_ids: Vec::new(),
772            header: RequestHeaderBuilder::new_from_session(session),
773        }
774    }
775
776    /// Construct a new call to the `DeleteSubscriptions` service, setting header parameters manually.
777    pub fn new_manual(
778        session_id: u32,
779        timeout: Duration,
780        auth_token: NodeId,
781        request_handle: IntegerId,
782    ) -> Self {
783        Self {
784            subscription_ids: Vec::new(),
785            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
786        }
787    }
788
789    /// Set the subscription IDs to delete, overwriting any that were added previously.
790    pub fn subscription_ids(mut self, subscription_ids: Vec<u32>) -> Self {
791        self.subscription_ids = subscription_ids;
792        self
793    }
794
795    /// Add a subscription ID to delete.
796    pub fn subscription(mut self, subscription_id: u32) -> Self {
797        self.subscription_ids.push(subscription_id);
798        self
799    }
800}
801
802impl UARequest for DeleteSubscriptions {
803    type Out = DeleteSubscriptionsResponse;
804
805    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
806    where
807        Self: 'a,
808    {
809        let span = debug_span!(
810            "Sending DeleteSubscriptions request",
811            subscription_ids = ?self.subscription_ids
812        );
813        let request = {
814            let _h = span.enter();
815            if self.subscription_ids.is_empty() {
816                builder_error!(self, "delete_subscriptions called with no subscription IDs");
817                return Err(Error::new(
818                    StatusCode::BadNothingToDo,
819                    "delete_subscriptions called with no subscription IDs",
820                ));
821            }
822            DeleteSubscriptionsRequest {
823                request_header: self.header.header,
824                subscription_ids: Some(self.subscription_ids.clone()),
825            }
826        };
827        let response = channel
828            .send(request, self.header.timeout)
829            .instrument(span.clone())
830            .await?;
831        let _h = span.enter();
832        if let ResponseMessage::DeleteSubscriptions(response) = response {
833            process_service_result(&response.response_header)?;
834
835            builder_debug!(self, "delete_subscriptions success");
836            Ok(*response)
837        } else {
838            builder_error!(self, "delete_subscriptions failed {:?}", response);
839            Err(process_unexpected_response(response))
840        }
841    }
842}
843
844#[derive(Clone)]
845/// Creates monitored items on a subscription by sending a [`CreateMonitoredItemsRequest`] to the server.
846///
847/// See OPC UA Part 4 - Services 5.12.2 for complete description of the service and error responses.
848pub struct CreateMonitoredItems<'a> {
849    subscription_id: u32,
850    timestamps_to_return: TimestampsToReturn,
851    items_to_create: Vec<MonitoredItemCreateRequest>,
852    handle: &'a AtomicHandle,
853
854    header: RequestHeaderBuilder,
855}
856
857builder_base!(CreateMonitoredItems<'a>);
858
859impl<'a> CreateMonitoredItems<'a> {
860    /// Construct a new call to the `CreateMonitoredItems` service.
861    pub fn new(subscription_id: u32, session: &'a Session) -> Self {
862        Self {
863            subscription_id,
864            timestamps_to_return: TimestampsToReturn::Neither,
865            items_to_create: Vec::new(),
866            handle: &session.monitored_item_handle,
867            header: RequestHeaderBuilder::new_from_session(session),
868        }
869    }
870
871    /// Construct a new call to the `CreateMonitoredItems` service, setting header parameters manually.
872    pub fn new_manual(
873        subscription_id: u32,
874        monitored_item_handle: &'a AtomicHandle,
875        session_id: u32,
876        timeout: Duration,
877        auth_token: NodeId,
878        request_handle: IntegerId,
879    ) -> Self {
880        Self {
881            subscription_id,
882            timestamps_to_return: TimestampsToReturn::Neither,
883            items_to_create: Vec::new(),
884            handle: monitored_item_handle,
885            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
886        }
887    }
888
889    /// An enumeration that specifies the timestamp Attributes to be transmitted for each MonitoredItem.
890    pub fn timestamps_to_return(mut self, timestamps_to_return: TimestampsToReturn) -> Self {
891        self.timestamps_to_return = timestamps_to_return;
892        self
893    }
894
895    /// Set the monitored items to create, overwriting any that were added previously.
896    pub fn items_to_create(mut self, items_to_create: Vec<MonitoredItemCreateRequest>) -> Self {
897        self.items_to_create = items_to_create;
898        self
899    }
900
901    /// Add a monitored item to create.
902    pub fn item(mut self, item: MonitoredItemCreateRequest) -> Self {
903        self.items_to_create.push(item);
904        self
905    }
906
907    /// Add a monitored item to create, subscribing to values on `node_id` with the
908    /// given `sampling_interval` and `queue_size`.
909    pub fn value(mut self, node_id: NodeId, sampling_interval: f64, queue_size: u32) -> Self {
910        self.items_to_create.push(MonitoredItemCreateRequest {
911            item_to_monitor: ReadValueId {
912                node_id,
913                attribute_id: AttributeId::Value as u32,
914                ..Default::default()
915            },
916            monitoring_mode: MonitoringMode::Reporting,
917            requested_parameters: MonitoringParameters {
918                client_handle: self.handle.next(),
919                sampling_interval,
920                queue_size,
921                discard_oldest: true,
922                ..Default::default()
923            },
924        });
925        self
926    }
927}
928
929#[derive(Debug, Clone)]
930/// The result of a [`CreateMonitoredItems`] request, including
931/// the requested parameters.
932pub struct CreatedMonitoredItem {
933    /// The monitored item result, including revised parameters.
934    pub result: MonitoredItemCreateResult,
935    /// The requested parameters.
936    pub requested_parameters: MonitoringParameters,
937    /// The requested monitoring mode.
938    pub monitoring_mode: MonitoringMode,
939    /// The requested item to monitor.
940    pub item_to_monitor: ReadValueId,
941}
942
943#[derive(Debug, Clone)]
944/// The result of a [`CreateMonitoredItems`] request, including
945/// the requested items.
946pub struct CreateMonitoredItemsResult {
947    /// The original response header.
948    pub response_header: ResponseHeader,
949    /// Optional diagnostic information, if requested.
950    pub diagnostic_infos: Option<Vec<DiagnosticInfo>>,
951    /// Created monitored items, with the requested parameters.
952    pub results: Vec<CreatedMonitoredItem>,
953}
954
955impl UARequest for CreateMonitoredItems<'_> {
956    type Out = CreateMonitoredItemsResult;
957
958    async fn send<'a>(mut self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
959    where
960        Self: 'a,
961    {
962        let span = debug_span!(
963            "Sending CreateMonitoredItems request",
964            subscription_id = self.subscription_id,
965            num_items = self.items_to_create.len(),
966            timestamps_to_return = ?self.timestamps_to_return
967        );
968        let num_items = self.items_to_create.len();
969
970        let request = {
971            let _h = span.enter();
972            if self.subscription_id == 0 {
973                builder_error!(self, "create_monitored_items, subscription id 0 is invalid");
974                return Err(Error::new(
975                    StatusCode::BadSubscriptionIdInvalid,
976                    "create_monitored_items, subscription id 0 is invalid",
977                ));
978            }
979
980            if self.items_to_create.is_empty() {
981                builder_error!(
982                    self,
983                    "create_monitored_items, called with no items to create"
984                );
985                return Err(Error::new(
986                    StatusCode::BadNothingToDo,
987                    "create_monitored_items, called with no items to create",
988                ));
989            }
990            for item in &mut self.items_to_create {
991                if item.requested_parameters.client_handle == 0 {
992                    item.requested_parameters.client_handle = self.handle.next();
993                }
994            }
995
996            CreateMonitoredItemsRequest {
997                request_header: self.header.header,
998                subscription_id: self.subscription_id,
999                timestamps_to_return: self.timestamps_to_return,
1000                items_to_create: Some(self.items_to_create.clone()),
1001            }
1002        };
1003
1004        let response = channel
1005            .send(request, self.header.timeout)
1006            .instrument(span.clone())
1007            .await?;
1008
1009        let _h = span.enter();
1010        if let ResponseMessage::CreateMonitoredItems(response) = response {
1011            process_service_result(&response.response_header)?;
1012            if let Some(ref results) = response.results {
1013                if results.len() != num_items {
1014                    builder_error!(
1015                        self,
1016                        "create_monitored_items, unexpected number of results. Got {}, expected {}",
1017                        results.len(),
1018                        num_items
1019                    );
1020                    return Err(Error::new(StatusCode::BadUnexpectedError, format!("create_monitored_items, unexpected number of results. Got {}, expected {}",
1021                        results.len(),
1022                        num_items)
1023                    ));
1024                }
1025                builder_debug!(self, "create_monitored_items, {} items created", num_items);
1026            } else {
1027                builder_error!(
1028                    self,
1029                    "create_monitored_items, success but no monitored items were created"
1030                );
1031                return Err(Error::new(
1032                    StatusCode::BadUnexpectedError,
1033                    "create_monitored_items, success but no monitored items were created",
1034                ));
1035            }
1036
1037            let created = response
1038                .results
1039                .unwrap_or_default()
1040                .into_iter()
1041                .zip(self.items_to_create)
1042                .map(|(result, item)| CreatedMonitoredItem {
1043                    result,
1044                    requested_parameters: item.requested_parameters,
1045                    monitoring_mode: item.monitoring_mode,
1046                    item_to_monitor: item.item_to_monitor,
1047                })
1048                .collect();
1049
1050            Ok(CreateMonitoredItemsResult {
1051                response_header: response.response_header,
1052                diagnostic_infos: response.diagnostic_infos,
1053                results: created,
1054            })
1055        } else {
1056            builder_error!(self, "create_monitored_items failed {:?}", response);
1057            Err(process_unexpected_response(response))
1058        }
1059    }
1060}
1061
1062#[derive(Clone)]
1063/// Modifies monitored items on a subscription by sending a [`ModifyMonitoredItemsRequest`] to the server.
1064///
1065/// See OPC UA Part 4 - Services 5.12.3 for complete description of the service and error responses.
1066pub struct ModifyMonitoredItems {
1067    subscription_id: u32,
1068    timestamps_to_return: TimestampsToReturn,
1069    items_to_modify: Vec<MonitoredItemModifyRequest>,
1070
1071    header: RequestHeaderBuilder,
1072}
1073
1074builder_base!(ModifyMonitoredItems);
1075
1076impl ModifyMonitoredItems {
1077    /// Construct a new call to the `ModifyMonitoredItems` service.
1078    pub fn new(subscription_id: u32, session: &Session) -> Self {
1079        Self {
1080            subscription_id,
1081            timestamps_to_return: TimestampsToReturn::Neither,
1082            items_to_modify: Vec::new(),
1083            header: RequestHeaderBuilder::new_from_session(session),
1084        }
1085    }
1086
1087    /// Construct a new call to the `ModifyMonitoredItems` service, setting header parameters manually.
1088    pub fn new_manual(
1089        subscription_id: u32,
1090        session_id: u32,
1091        timeout: Duration,
1092        auth_token: NodeId,
1093        request_handle: IntegerId,
1094    ) -> Self {
1095        Self {
1096            subscription_id,
1097            timestamps_to_return: TimestampsToReturn::Neither,
1098            items_to_modify: Vec::new(),
1099            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
1100        }
1101    }
1102
1103    /// An enumeration that specifies the timestamp Attributes to be transmitted for each MonitoredItem.
1104    pub fn timestamps_to_return(mut self, timestamps_to_return: TimestampsToReturn) -> Self {
1105        self.timestamps_to_return = timestamps_to_return;
1106        self
1107    }
1108
1109    /// Set the monitored items to modify, overwriting any that were added previously.
1110    pub fn items_to_modify(mut self, items_to_modify: Vec<MonitoredItemModifyRequest>) -> Self {
1111        self.items_to_modify = items_to_modify;
1112        self
1113    }
1114
1115    /// Add a monitored item to modify.
1116    pub fn item(mut self, item: MonitoredItemModifyRequest) -> Self {
1117        self.items_to_modify.push(item);
1118        self
1119    }
1120}
1121
1122impl UARequest for ModifyMonitoredItems {
1123    type Out = ModifyMonitoredItemsResponse;
1124
1125    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
1126    where
1127        Self: 'a,
1128    {
1129        let span = debug_span!(
1130            "Sending ModifyMonitoredItems request",
1131            subscription_id = self.subscription_id,
1132            num_items = self.items_to_modify.len(),
1133            timestamps_to_return = ?self.timestamps_to_return
1134        );
1135        let num_items = self.items_to_modify.len();
1136        let request = {
1137            let _h = span.enter();
1138            if self.subscription_id == 0 {
1139                builder_error!(self, "modify_monitored_items, subscription id 0 is invalid");
1140                return Err(Error::new(
1141                    StatusCode::BadInvalidArgument,
1142                    "modify_monitored_items, subscription id 0 is invalid",
1143                ));
1144            }
1145            if self.items_to_modify.is_empty() {
1146                builder_error!(
1147                    self,
1148                    "modify_monitored_items, called with no items to modify"
1149                );
1150                return Err(Error::new(
1151                    StatusCode::BadNothingToDo,
1152                    "modify_monitored_items, called with no items to modify",
1153                ));
1154            }
1155            ModifyMonitoredItemsRequest {
1156                request_header: self.header.header,
1157                subscription_id: self.subscription_id,
1158                timestamps_to_return: self.timestamps_to_return,
1159                items_to_modify: Some(self.items_to_modify),
1160            }
1161        };
1162        let response = channel
1163            .send(request, self.header.timeout)
1164            .instrument(span.clone())
1165            .await?;
1166        let _h = span.enter();
1167        if let ResponseMessage::ModifyMonitoredItems(response) = response {
1168            process_service_result(&response.response_header)?;
1169            let Some(results) = &response.results else {
1170                builder_error!(self, "modify_monitored_items, got empty response");
1171                return Err(Error::new(
1172                    StatusCode::BadUnexpectedError,
1173                    "modify_monitored_items, got empty response",
1174                ));
1175            };
1176            if results.len() != num_items {
1177                builder_error!(
1178                    self,
1179                    "modify_monitored_items, unexpected number of results. Expected {}, got {}",
1180                    num_items,
1181                    results.len()
1182                );
1183                return Err(Error::new(
1184                    StatusCode::BadUnexpectedError,
1185                    format!(
1186                        "modify_monitored_items, unexpected number of results. Expected {}, got {}",
1187                        num_items,
1188                        results.len()
1189                    ),
1190                ));
1191            }
1192
1193            builder_debug!(self, "modify_monitored_items, success");
1194            Ok(*response)
1195        } else {
1196            builder_error!(self, "modify_monitored_items failed {:?}", response);
1197            Err(process_unexpected_response(response))
1198        }
1199    }
1200}
1201
1202#[derive(Clone)]
1203/// Sets the monitoring mode on one or more monitored items by sending a [`SetMonitoringModeRequest`]
1204/// to the server.
1205///
1206/// See OPC UA Part 4 - Services 5.12.4 for complete description of the service and error responses.
1207pub struct SetMonitoringMode {
1208    subscription_id: u32,
1209    monitoring_mode: MonitoringMode,
1210    monitored_item_ids: Vec<u32>,
1211
1212    header: RequestHeaderBuilder,
1213}
1214
1215builder_base!(SetMonitoringMode);
1216
1217impl SetMonitoringMode {
1218    /// Construct a new call to the `SetMonitoringMode` service.
1219    pub fn new(subscription_id: u32, monitoring_mode: MonitoringMode, session: &Session) -> Self {
1220        Self {
1221            subscription_id,
1222            monitored_item_ids: Vec::new(),
1223            monitoring_mode,
1224            header: RequestHeaderBuilder::new_from_session(session),
1225        }
1226    }
1227
1228    /// Construct a new call to the `SetMonitoringMode` service, setting header parameters manually.
1229    pub fn new_manual(
1230        subscription_id: u32,
1231        monitoring_mode: MonitoringMode,
1232        session_id: u32,
1233        timeout: Duration,
1234        auth_token: NodeId,
1235        request_handle: IntegerId,
1236    ) -> Self {
1237        Self {
1238            subscription_id,
1239            monitored_item_ids: Vec::new(),
1240            monitoring_mode,
1241            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
1242        }
1243    }
1244
1245    /// Set the monitored items to modify, overwriting any that were added previously.
1246    pub fn monitored_item_ids(mut self, monitored_item_ids: Vec<u32>) -> Self {
1247        self.monitored_item_ids = monitored_item_ids;
1248        self
1249    }
1250
1251    /// Add a monitored item to modify.
1252    pub fn item(mut self, item: u32) -> Self {
1253        self.monitored_item_ids.push(item);
1254        self
1255    }
1256}
1257
1258impl UARequest for SetMonitoringMode {
1259    type Out = SetMonitoringModeResponse;
1260
1261    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
1262    where
1263        Self: 'a,
1264    {
1265        let span = debug_span!(
1266            "Sending SetMonitoringMode request",
1267            subscription_id = self.subscription_id,
1268            monitoring_mode = ?self.monitoring_mode,
1269            num_items = self.monitored_item_ids.len()
1270        );
1271        let num_items = self.monitored_item_ids.len();
1272
1273        let request = {
1274            let _h = span.enter();
1275            if self.subscription_id == 0 {
1276                builder_error!(self, "set_monitoring_mode, subscription id 0 is invalid");
1277                return Err(Error::new(
1278                    StatusCode::BadInvalidArgument,
1279                    "set_monitoring_mode, subscription id 0 is invalid",
1280                ));
1281            }
1282            if self.monitored_item_ids.is_empty() {
1283                builder_error!(self, "set_monitoring_mode, called with no items to modify");
1284                return Err(Error::new(
1285                    StatusCode::BadNothingToDo,
1286                    "set_monitoring_mode, subscription id 0 is invalid",
1287                ));
1288            }
1289
1290            SetMonitoringModeRequest {
1291                request_header: self.header.header,
1292                subscription_id: self.subscription_id,
1293                monitoring_mode: self.monitoring_mode,
1294                monitored_item_ids: Some(self.monitored_item_ids),
1295            }
1296        };
1297        let response = channel.send(request, self.header.timeout).await?;
1298        let _h = span.enter();
1299        if let ResponseMessage::SetMonitoringMode(response) = response {
1300            let Some(results) = &response.results else {
1301                builder_error!(self, "set_monitoring_mode, got empty response");
1302                return Err(Error::new(
1303                    StatusCode::BadUnexpectedError,
1304                    "set_monitoring_mode, got empty response",
1305                ));
1306            };
1307            if results.len() != num_items {
1308                builder_error!(
1309                    self,
1310                    "set_monitoring_mode, unexpected number of results. Expected {}, got {}",
1311                    num_items,
1312                    results.len()
1313                );
1314                return Err(Error::new(
1315                    StatusCode::BadUnexpectedError,
1316                    format!(
1317                        "set_monitoring_mode, unexpected number of results. Expected {}, got {}",
1318                        num_items,
1319                        results.len()
1320                    ),
1321                ));
1322            }
1323
1324            Ok(*response)
1325        } else {
1326            builder_error!(self, "set_monitoring_mode failed {:?}", response);
1327            Err(process_unexpected_response(response))
1328        }
1329    }
1330}
1331
1332#[derive(Clone)]
1333/// Sets a monitored item so it becomes the trigger that causes other monitored items to send
1334/// change events in the same update. Sends a [`SetTriggeringRequest`] to the server.
1335/// Note that `items_to_remove` is applied before `items_to_add`.
1336///
1337/// See OPC UA Part 4 - Services 5.12.5 for complete description of the service and error responses.
1338pub struct SetTriggering {
1339    subscription_id: u32,
1340    triggering_item_id: u32,
1341    links_to_add: Vec<u32>,
1342    links_to_remove: Vec<u32>,
1343
1344    header: RequestHeaderBuilder,
1345}
1346
1347builder_base!(SetTriggering);
1348
1349impl SetTriggering {
1350    /// Construct a new call to the `SetTriggering` service.
1351    pub fn new(subscription_id: u32, triggering_item_id: u32, session: &Session) -> Self {
1352        Self {
1353            subscription_id,
1354            triggering_item_id,
1355            links_to_add: Vec::new(),
1356            links_to_remove: Vec::new(),
1357            header: RequestHeaderBuilder::new_from_session(session),
1358        }
1359    }
1360
1361    /// Construct a new call to the `SetTriggering` service, setting header parameters manually.
1362    pub fn new_manual(
1363        subscription_id: u32,
1364        triggering_item_id: u32,
1365        session_id: u32,
1366        timeout: Duration,
1367        auth_token: NodeId,
1368        request_handle: IntegerId,
1369    ) -> Self {
1370        Self {
1371            subscription_id,
1372            triggering_item_id,
1373            links_to_add: Vec::new(),
1374            links_to_remove: Vec::new(),
1375            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
1376        }
1377    }
1378
1379    /// Set the links to add, overwriting any that were added previously.
1380    pub fn links_to_add(mut self, links_to_add: Vec<u32>) -> Self {
1381        self.links_to_add = links_to_add;
1382        self
1383    }
1384
1385    /// Add a new trigger target.
1386    pub fn add_link(mut self, item: u32) -> Self {
1387        self.links_to_add.push(item);
1388        self
1389    }
1390
1391    /// Set the links to add, overwriting any that were added previously.
1392    pub fn links_to_remove(mut self, links_to_remove: Vec<u32>) -> Self {
1393        self.links_to_remove = links_to_remove;
1394        self
1395    }
1396
1397    /// Add a new trigger to remove.
1398    pub fn remove_link(mut self, item: u32) -> Self {
1399        self.links_to_remove.push(item);
1400        self
1401    }
1402}
1403
1404impl UARequest for SetTriggering {
1405    type Out = SetTriggeringResponse;
1406
1407    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
1408    where
1409        Self: 'a,
1410    {
1411        let span = debug_span!(
1412            "Sending SetTriggering request",
1413            subscription_id = self.subscription_id,
1414            triggering_item_id = self.triggering_item_id,
1415            num_links_to_add = self.links_to_add.len(),
1416            num_links_to_remove = self.links_to_remove.len()
1417        );
1418        let request = {
1419            let _h = span.enter();
1420            if self.subscription_id == 0 {
1421                builder_error!(self, "set_triggering, subscription id 0 is invalid");
1422                return Err(Error::new(
1423                    StatusCode::BadInvalidArgument,
1424                    "set_triggering, subscription id 0 is invalid",
1425                ));
1426            }
1427
1428            if self.links_to_add.is_empty() && self.links_to_remove.is_empty() {
1429                builder_error!(self, "set_triggering, called with nothing to add or remove");
1430                return Err(Error::new(
1431                    StatusCode::BadNothingToDo,
1432                    "set_triggering, subscription id 0 is invalid",
1433                ));
1434            }
1435            SetTriggeringRequest {
1436                request_header: self.header.header,
1437                subscription_id: self.subscription_id,
1438                triggering_item_id: self.triggering_item_id,
1439                links_to_add: if self.links_to_add.is_empty() {
1440                    None
1441                } else {
1442                    Some(self.links_to_add.clone())
1443                },
1444                links_to_remove: if self.links_to_remove.is_empty() {
1445                    None
1446                } else {
1447                    Some(self.links_to_remove.clone())
1448                },
1449            }
1450        };
1451
1452        let response = channel
1453            .send(request, self.header.timeout)
1454            .instrument(span.clone())
1455            .await?;
1456        let _h = span.enter();
1457        if let ResponseMessage::SetTriggering(response) = response {
1458            let to_add_res = response.add_results.as_deref().unwrap_or(&[]);
1459            let to_remove_res = response.remove_results.as_deref().unwrap_or(&[]);
1460            if to_add_res.len() != self.links_to_add.len() {
1461                builder_error!(
1462                    self,
1463                    "set_triggering, got unexpected number of add results: {}, expected {}",
1464                    to_add_res.len(),
1465                    self.links_to_add.len()
1466                );
1467                return Err(Error::new(
1468                    StatusCode::BadUnexpectedError,
1469                    format!(
1470                        "set_triggering, got unexpected number of add results: {}, expected {}",
1471                        to_add_res.len(),
1472                        self.links_to_add.len()
1473                    ),
1474                ));
1475            }
1476            if to_remove_res.len() != self.links_to_remove.len() {
1477                builder_error!(
1478                    self,
1479                    "set_triggering, got unexpected number of remove results: {}, expected {}",
1480                    to_remove_res.len(),
1481                    self.links_to_add.len()
1482                );
1483                return Err(Error::new(
1484                    StatusCode::BadUnexpectedError,
1485                    format!(
1486                        "set_triggering, got unexpected number of remove results: {}, expected {}",
1487                        to_remove_res.len(),
1488                        self.links_to_add.len()
1489                    ),
1490                ));
1491            }
1492
1493            Ok(*response)
1494        } else {
1495            builder_error!(self, "set_triggering failed {:?}", response);
1496            Err(process_unexpected_response(response))
1497        }
1498    }
1499}
1500
1501#[derive(Clone)]
1502/// Deletes monitored items from a subscription by sending a [`DeleteMonitoredItemsRequest`] to the server.
1503///
1504/// See OPC UA Part 4 - Services 5.12.6 for complete description of the service and error responses.
1505pub struct DeleteMonitoredItems {
1506    subscription_id: u32,
1507    items_to_delete: Vec<u32>,
1508
1509    header: RequestHeaderBuilder,
1510}
1511
1512builder_base!(DeleteMonitoredItems);
1513
1514impl DeleteMonitoredItems {
1515    /// Construct a new call to the `DeleteMonitoredItems` service.
1516    pub fn new(subscription_id: u32, session: &Session) -> Self {
1517        Self {
1518            subscription_id,
1519            items_to_delete: Vec::new(),
1520            header: RequestHeaderBuilder::new_from_session(session),
1521        }
1522    }
1523
1524    /// Construct a new call to the `DeleteMonitoredItems` service, setting header parameters manually.
1525    pub fn new_manual(
1526        subscription_id: u32,
1527        session_id: u32,
1528        timeout: Duration,
1529        auth_token: NodeId,
1530        request_handle: IntegerId,
1531    ) -> Self {
1532        Self {
1533            subscription_id,
1534            items_to_delete: Vec::new(),
1535            header: RequestHeaderBuilder::new(session_id, timeout, auth_token, request_handle),
1536        }
1537    }
1538
1539    /// Set the items to delete, overwriting any that were added previously.
1540    pub fn items_to_delete(mut self, items_to_delete: Vec<u32>) -> Self {
1541        self.items_to_delete = items_to_delete;
1542        self
1543    }
1544
1545    /// Add a new item to delete.
1546    pub fn item(mut self, item: u32) -> Self {
1547        self.items_to_delete.push(item);
1548        self
1549    }
1550}
1551
1552impl UARequest for DeleteMonitoredItems {
1553    type Out = DeleteMonitoredItemsResponse;
1554
1555    async fn send<'a>(self, channel: &'a crate::AsyncSecureChannel) -> Result<Self::Out, Error>
1556    where
1557        Self: 'a,
1558    {
1559        let span = debug_span!(
1560            "Sending DeleteMonitoredItems request",
1561            subscription_id = self.subscription_id,
1562            num_items_to_delete = self.items_to_delete.len()
1563        );
1564        let request = {
1565            let _h = span.enter();
1566            if self.subscription_id == 0 {
1567                builder_error!(self, "delete_monitored_items, subscription id 0 is invalid");
1568                return Err(Error::new(
1569                    StatusCode::BadInvalidArgument,
1570                    "delete_monitored_items, subscription id 0 is invalid",
1571                ));
1572            }
1573            if self.items_to_delete.is_empty() {
1574                builder_error!(
1575                    self,
1576                    "delete_monitored_items, called with no items to delete"
1577                );
1578                return Err(Error::new(
1579                    StatusCode::BadNothingToDo,
1580                    "delete_monitored_items, called with no items to delete",
1581                ));
1582            }
1583
1584            DeleteMonitoredItemsRequest {
1585                request_header: self.header.header,
1586                subscription_id: self.subscription_id,
1587                monitored_item_ids: Some(self.items_to_delete.clone()),
1588            }
1589        };
1590
1591        let response = channel
1592            .send(request, self.header.timeout)
1593            .instrument(span.clone())
1594            .await?;
1595        let _h = span.enter();
1596        if let ResponseMessage::DeleteMonitoredItems(response) = response {
1597            process_service_result(&response.response_header)?;
1598            builder_debug!(self, "delete_monitored_items, success");
1599            Ok(*response)
1600        } else {
1601            builder_error!(self, "delete_monitored_items failed {:?}", response);
1602            Err(process_unexpected_response(response))
1603        }
1604    }
1605}
1606
1607impl Session {
1608    /// Get the internal state of subscriptions registered on the session.
1609    pub fn subscription_state(&self) -> &Mutex<SubscriptionState> {
1610        &self.subscription_state
1611    }
1612
1613    /// Trigger a publish to fire immediately.
1614    pub fn trigger_publish_now(&self) {
1615        let _ = self.trigger_publish_tx.send(Instant::now());
1616    }
1617
1618    #[allow(clippy::too_many_arguments)]
1619    async fn create_subscription_inner(
1620        &self,
1621        publishing_interval: Duration,
1622        lifetime_count: u32,
1623        max_keep_alive_count: u32,
1624        max_notifications_per_publish: u32,
1625        publishing_enabled: bool,
1626        priority: u8,
1627        callback: Box<dyn OnSubscriptionNotificationCore>,
1628    ) -> Result<u32, Error> {
1629        let response = CreateSubscription::new(self)
1630            .publishing_interval(publishing_interval)
1631            .max_lifetime_count(lifetime_count)
1632            .max_keep_alive_count(max_keep_alive_count)
1633            .max_notifications_per_publish(max_notifications_per_publish)
1634            .publishing_enabled(publishing_enabled)
1635            .priority(priority)
1636            .send(&self.channel)
1637            .await?;
1638
1639        let revised_publishing_interval = if response.revised_publishing_interval.is_finite() {
1640            response.revised_publishing_interval.max(0.0).floor() as u64
1641        } else {
1642            0
1643        };
1644        let subscription = Subscription::new(
1645            response.subscription_id,
1646            Duration::from_millis(revised_publishing_interval),
1647            response.revised_lifetime_count,
1648            response.revised_max_keep_alive_count,
1649            max_notifications_per_publish,
1650            priority,
1651            publishing_enabled,
1652            callback,
1653        );
1654        {
1655            let mut subscription_state = trace_lock!(self.subscription_state);
1656            subscription_state.add_subscription(subscription);
1657        }
1658
1659        self.trigger_publish_now();
1660
1661        Ok(response.subscription_id)
1662    }
1663
1664    /// Create a subscription by sending a [`CreateSubscriptionRequest`] to the server.
1665    ///
1666    /// See OPC UA Part 4 - Services 5.13.2 for complete description of the service and error responses.
1667    ///
1668    /// # Arguments
1669    ///
1670    /// * `publishing_interval` - The requested publishing interval defines the cyclic rate that
1671    ///   the Subscription is being requested to return Notifications to the Client. This interval
1672    ///   is expressed in milliseconds. This interval is represented by the publishing timer in the
1673    ///   Subscription state table. The negotiated value for this parameter returned in the
1674    ///   response is used as the default sampling interval for MonitoredItems assigned to this
1675    ///   Subscription. If the requested value is 0 or negative, the server shall revise with the
1676    ///   fastest supported publishing interval in milliseconds.
1677    /// * `lifetime_count` - Requested lifetime count. The lifetime count shall be a minimum of
1678    ///   three times the keep keep-alive count. When the publishing timer has expired this
1679    ///   number of times without a Publish request being available to send a NotificationMessage,
1680    ///   then the Subscription shall be deleted by the Server.
1681    /// * `max_keep_alive_count` - Requested maximum keep-alive count. When the publishing timer has
1682    ///   expired this number of times without requiring any NotificationMessage to be sent, the
1683    ///   Subscription sends a keep-alive Message to the Client. The negotiated value for this
1684    ///   parameter is returned in the response. If the requested value is 0, the server shall
1685    ///   revise with the smallest supported keep-alive count.
1686    /// * `max_notifications_per_publish` - The maximum number of notifications that the Client
1687    ///   wishes to receive in a single Publish response. A value of zero indicates that there is
1688    ///   no limit. The number of notifications per Publish is the sum of monitoredItems in
1689    ///   the DataChangeNotification and events in the EventNotificationList.
1690    /// * `priority` - Indicates the relative priority of the Subscription. When more than one
1691    ///   Subscription needs to send Notifications, the Server should de-queue a Publish request
1692    ///   to the Subscription with the highest priority number. For Subscriptions with equal
1693    ///   priority the Server should de-queue Publish requests in a round-robin fashion.
1694    ///   A Client that does not require special priority settings should set this value to zero.
1695    /// * `publishing_enabled` - A boolean parameter with the following values - `true` publishing
1696    ///   is enabled for the Subscription, `false`, publishing is disabled for the Subscription.
1697    ///   The value of this parameter does not affect the value of the monitoring mode Attribute of
1698    ///   MonitoredItems.
1699    ///
1700    /// # Returns
1701    ///
1702    /// * `Ok(u32)` - identifier for new subscription
1703    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
1704    ///
1705    #[allow(clippy::too_many_arguments)]
1706    pub async fn create_subscription(
1707        &self,
1708        publishing_interval: Duration,
1709        lifetime_count: u32,
1710        max_keep_alive_count: u32,
1711        max_notifications_per_publish: u32,
1712        priority: u8,
1713        publishing_enabled: bool,
1714        callback: impl OnSubscriptionNotificationCore + 'static,
1715    ) -> Result<u32, Error> {
1716        self.create_subscription_inner(
1717            publishing_interval,
1718            lifetime_count,
1719            max_keep_alive_count,
1720            max_notifications_per_publish,
1721            publishing_enabled,
1722            priority,
1723            Box::new(callback),
1724        )
1725        .await
1726    }
1727
1728    fn subscription_exists(&self, subscription_id: u32) -> bool {
1729        let subscription_state = trace_lock!(self.subscription_state);
1730        subscription_state.subscription_exists(subscription_id)
1731    }
1732
1733    /// Modifies a subscription by sending a [`ModifySubscriptionRequest`] to the server.
1734    ///
1735    /// See OPC UA Part 4 - Services 5.13.3 for complete description of the service and error responses.
1736    ///
1737    /// # Arguments
1738    ///
1739    /// * `subscription_id` - subscription identifier returned from `create_subscription`.
1740    /// * `publishing_interval` - The requested publishing interval defines the cyclic rate that
1741    ///   the Subscription is being requested to return Notifications to the Client. This interval
1742    ///   is expressed in milliseconds. This interval is represented by the publishing timer in the
1743    ///   Subscription state table. The negotiated value for this parameter returned in the
1744    ///   response is used as the default sampling interval for MonitoredItems assigned to this
1745    ///   Subscription. If the requested value is 0 or negative, the server shall revise with the
1746    ///   fastest supported publishing interval in milliseconds.
1747    /// * `lifetime_count` - Requested lifetime count. The lifetime count shall be a minimum of
1748    ///   three times the keep keep-alive count. When the publishing timer has expired this
1749    ///   number of times without a Publish request being available to send a NotificationMessage,
1750    ///   then the Subscription shall be deleted by the Server.
1751    /// * `max_keep_alive_count` - Requested maximum keep-alive count. When the publishing timer has
1752    ///   expired this number of times without requiring any NotificationMessage to be sent, the
1753    ///   Subscription sends a keep-alive Message to the Client. The negotiated value for this
1754    ///   parameter is returned in the response. If the requested value is 0, the server shall
1755    ///   revise with the smallest supported keep-alive count.
1756    /// * `max_notifications_per_publish` - The maximum number of notifications that the Client
1757    ///   wishes to receive in a single Publish response. A value of zero indicates that there is
1758    ///   no limit. The number of notifications per Publish is the sum of monitoredItems in
1759    ///   the DataChangeNotification and events in the EventNotificationList.
1760    /// * `priority` - Indicates the relative priority of the Subscription. When more than one
1761    ///   Subscription needs to send Notifications, the Server should de-queue a Publish request
1762    ///   to the Subscription with the highest priority number. For Subscriptions with equal
1763    ///   priority the Server should de-queue Publish requests in a round-robin fashion.
1764    ///   A Client that does not require special priority settings should set this value to zero.
1765    ///
1766    /// # Returns
1767    ///
1768    /// * `Ok(())` - Success
1769    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
1770    ///
1771    pub async fn modify_subscription(
1772        &self,
1773        subscription_id: u32,
1774        publishing_interval: Duration,
1775        lifetime_count: u32,
1776        max_keep_alive_count: u32,
1777        max_notifications_per_publish: u32,
1778        priority: u8,
1779    ) -> Result<(), Error> {
1780        if !self.subscription_exists(subscription_id) {
1781            session_error!(self, "modify_subscription, subscription id does not exist");
1782            return Err(Error::new(
1783                StatusCode::BadInvalidArgument,
1784                "modify_subscription, subscription id does not exist",
1785            ));
1786        }
1787
1788        let response = ModifySubscription::new(subscription_id, self)
1789            .publishing_interval(publishing_interval)
1790            .max_lifetime_count(lifetime_count)
1791            .max_keep_alive_count(max_keep_alive_count)
1792            .max_notifications_per_publish(max_notifications_per_publish)
1793            .priority(priority)
1794            .send(&self.channel)
1795            .await?;
1796
1797        {
1798            let mut subscription_state = trace_lock!(self.subscription_state);
1799            subscription_state.modify_subscription(
1800                subscription_id,
1801                Duration::from_millis(response.revised_publishing_interval.max(0.0).floor() as u64),
1802                response.revised_lifetime_count,
1803                response.revised_max_keep_alive_count,
1804                max_notifications_per_publish,
1805                priority,
1806            );
1807        }
1808
1809        Ok(())
1810    }
1811
1812    /// Changes the publishing mode of subscriptions by sending a [`SetPublishingModeRequest`] to the server.
1813    ///
1814    /// See OPC UA Part 4 - Services 5.13.4 for complete description of the service and error responses.
1815    ///
1816    /// # Arguments
1817    ///
1818    /// * `subscription_ids` - one or more subscription identifiers.
1819    /// * `publishing_enabled` - A boolean parameter with the following values - `true` publishing
1820    ///   is enabled for the Subscriptions, `false`, publishing is disabled for the Subscriptions.
1821    ///
1822    /// # Returns
1823    ///
1824    /// * `Ok(Vec<StatusCode>)` - Service return code for the action for each id, `Good` or `BadSubscriptionIdInvalid`
1825    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
1826    ///
1827    pub async fn set_publishing_mode(
1828        &self,
1829        subscription_ids: &[u32],
1830        publishing_enabled: bool,
1831    ) -> Result<Vec<StatusCode>, Error> {
1832        let results = SetPublishingMode::new(publishing_enabled, self)
1833            .subscription_ids(subscription_ids.to_vec())
1834            .send(&self.channel)
1835            .await?
1836            .results
1837            .unwrap_or_default();
1838
1839        {
1840            // Update all subscriptions where the returned status is good.
1841            let mut subscription_state = trace_lock!(self.subscription_state);
1842            let ids = subscription_ids
1843                .iter()
1844                .zip(results.iter())
1845                .filter(|(_, s)| s.is_good())
1846                .map(|(v, _)| *v)
1847                .collect::<Vec<_>>();
1848            subscription_state.set_publishing_mode(&ids, publishing_enabled);
1849        }
1850
1851        if publishing_enabled {
1852            self.trigger_publish_now();
1853        }
1854        Ok(results)
1855    }
1856
1857    /// Transfers Subscriptions and their MonitoredItems from one Session to another. For example,
1858    /// a Client may need to reopen a Session and then transfer its Subscriptions to that Session.
1859    /// It may also be used by one Client to take over a Subscription from another Client by
1860    /// transferring the Subscription to its Session.
1861    ///
1862    /// Note that if you call this manually, you will need to register the
1863    /// subscriptions in the subscription state ([`Session::subscription_state`]) in order to
1864    /// receive notifications.
1865    ///
1866    /// See OPC UA Part 4 - Services 5.13.7 for complete description of the service and error responses.
1867    ///
1868    /// * `subscription_ids` - one or more subscription identifiers.
1869    /// * `send_initial_values` - A boolean parameter with the following values - `true` the first
1870    ///   publish response shall contain the current values of all monitored items in the subscription,
1871    ///   `false`, the first publish response shall contain only the value changes since the last
1872    ///   publish response was sent.
1873    ///
1874    /// # Returns
1875    ///
1876    /// * `Ok(Vec<TransferResult>)` - The [`TransferResult`] for each transfer subscription.
1877    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
1878    ///
1879    pub async fn transfer_subscriptions(
1880        &self,
1881        subscription_ids: &[u32],
1882        send_initial_values: bool,
1883    ) -> Result<Vec<TransferResult>, Error> {
1884        let r = TransferSubscriptions::new(self)
1885            .send_initial_values(send_initial_values)
1886            .subscription_ids(subscription_ids.to_vec())
1887            .send(&self.channel)
1888            .await?
1889            .results
1890            .unwrap_or_default();
1891
1892        self.trigger_publish_now();
1893
1894        Ok(r)
1895    }
1896
1897    /// Deletes a subscription by sending a [`DeleteSubscriptionsRequest`] to the server.
1898    ///
1899    /// See OPC UA Part 4 - Services 5.13.8 for complete description of the service and error responses.
1900    ///
1901    /// # Arguments
1902    ///
1903    /// * `subscription_id` - subscription identifier returned from `create_subscription`.
1904    ///
1905    /// # Returns
1906    ///
1907    /// * `Ok(StatusCode)` - Service return code for the delete action, `Good` or `BadSubscriptionIdInvalid`
1908    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
1909    ///
1910    pub async fn delete_subscription(&self, subscription_id: u32) -> Result<StatusCode, Error> {
1911        if subscription_id == 0 {
1912            session_error!(self, "delete_subscription, subscription id 0 is invalid");
1913            Err(Error::new(
1914                StatusCode::BadInvalidArgument,
1915                "delete_subscription, subscription id 0 is invalid",
1916            ))
1917        } else if !self.subscription_exists(subscription_id) {
1918            session_error!(
1919                self,
1920                "delete_subscription, subscription id {} does not exist",
1921                subscription_id
1922            );
1923            Err(Error::new(
1924                StatusCode::BadInvalidArgument,
1925                format!(
1926                    "delete_subscription, subscription id {} does not exist",
1927                    subscription_id
1928                ),
1929            ))
1930        } else {
1931            let result = self.delete_subscriptions(&[subscription_id]).await?;
1932            Ok(result[0])
1933        }
1934    }
1935
1936    /// Deletes subscriptions by sending a [`DeleteSubscriptionsRequest`] to the server with the list
1937    /// of subscriptions to delete.
1938    ///
1939    /// See OPC UA Part 4 - Services 5.13.8 for complete description of the service and error responses.
1940    ///
1941    /// # Arguments
1942    ///
1943    /// * `subscription_ids` - List of subscription identifiers to delete.
1944    ///
1945    /// # Returns
1946    ///
1947    /// * `Ok(Vec<StatusCode>)` - List of result for delete action on each id, `Good` or `BadSubscriptionIdInvalid`
1948    ///   The size and order of the list matches the size and order of the input.
1949    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
1950    ///
1951    pub async fn delete_subscriptions(
1952        &self,
1953        subscription_ids: &[u32],
1954    ) -> Result<Vec<StatusCode>, Error> {
1955        let result = DeleteSubscriptions::new(self)
1956            .subscription_ids(subscription_ids.to_vec())
1957            .send(&self.channel)
1958            .await?
1959            .results
1960            .unwrap_or_default();
1961        {
1962            // Clear out deleted subscriptions, assuming the delete worked
1963            let mut subscription_state = trace_lock!(self.subscription_state);
1964            for id in subscription_ids {
1965                subscription_state.delete_subscription(*id);
1966            }
1967        }
1968
1969        Ok(result)
1970    }
1971
1972    /// Creates monitored items on a subscription by sending a [`CreateMonitoredItemsRequest`] to the server.
1973    ///
1974    /// See OPC UA Part 4 - Services 5.12.2 for complete description of the service and error responses.
1975    ///
1976    /// # Arguments
1977    ///
1978    /// * `subscription_id` - The Server-assigned identifier for the Subscription that will report Notifications for this MonitoredItem
1979    /// * `timestamps_to_return` - An enumeration that specifies the timestamp Attributes to be transmitted for each MonitoredItem.
1980    /// * `items_to_create` - A list of [`MonitoredItemCreateRequest`] to be created and assigned to the specified Subscription.
1981    ///
1982    /// # Returns
1983    ///
1984    /// * `Ok(Vec<MonitoredItemCreateResult>)` - A list of [`MonitoredItemCreateResult`] corresponding to the items to create.
1985    ///   The size and order of the list matches the size and order of the `items_to_create` request parameter.
1986    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
1987    ///
1988    pub async fn create_monitored_items(
1989        &self,
1990        subscription_id: u32,
1991        timestamps_to_return: TimestampsToReturn,
1992        mut items_to_create: Vec<MonitoredItemCreateRequest>,
1993    ) -> Result<Vec<CreatedMonitoredItem>, Error> {
1994        {
1995            let state = trace_lock!(self.subscription_state);
1996            if !state.subscription_exists(subscription_id) {
1997                session_error!(
1998                    self,
1999                    "create_monitored_items, subscription id {} does not exist",
2000                    subscription_id
2001                );
2002                return Err(Error::new(
2003                    StatusCode::BadSubscriptionIdInvalid,
2004                    format!(
2005                        "create_monitored_items, subscription id {} does not exist",
2006                        subscription_id
2007                    ),
2008                ));
2009            }
2010        }
2011
2012        for item in &mut items_to_create {
2013            if item.requested_parameters.client_handle == 0 {
2014                item.requested_parameters.client_handle = self.monitored_item_handle.next();
2015            }
2016        }
2017
2018        // Add the monitored items _before_ making the request, to avoid
2019        // race conditions where publish responses arrive before the monitored items
2020        // are added to the internal state.
2021        let pre_insert = PreInsertMonitoredItems::new(
2022            &self.subscription_state,
2023            subscription_id,
2024            &items_to_create,
2025        );
2026
2027        let result = CreateMonitoredItems::new(subscription_id, self)
2028            .items_to_create(items_to_create)
2029            .timestamps_to_return(timestamps_to_return)
2030            .send(&self.channel)
2031            .await?;
2032
2033        // Set the items in our internal state
2034        pre_insert.finish(&result.results);
2035
2036        Ok(result.results)
2037    }
2038
2039    /// Modifies monitored items on a subscription by sending a [`ModifyMonitoredItemsRequest`] to the server.
2040    ///
2041    /// See OPC UA Part 4 - Services 5.12.3 for complete description of the service and error responses.
2042    ///
2043    /// # Arguments
2044    ///
2045    /// * `subscription_id` - The Server-assigned identifier for the Subscription that will report Notifications for this MonitoredItem.
2046    /// * `timestamps_to_return` - An enumeration that specifies the timestamp Attributes to be transmitted for each MonitoredItem.
2047    /// * `items_to_modify` - The list of [`MonitoredItemModifyRequest`] to modify.
2048    ///
2049    /// # Returns
2050    ///
2051    /// * `Ok(Vec<MonitoredItemModifyResult>)` - A list of [`MonitoredItemModifyResult`] corresponding to the MonitoredItems to modify.
2052    ///   The size and order of the list matches the size and order of the `items_to_modify` request parameter.
2053    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
2054    ///
2055    pub async fn modify_monitored_items(
2056        &self,
2057        subscription_id: u32,
2058        timestamps_to_return: TimestampsToReturn,
2059        items_to_modify: &[MonitoredItemModifyRequest],
2060    ) -> Result<Vec<MonitoredItemModifyResult>, Error> {
2061        {
2062            let state = trace_lock!(self.subscription_state);
2063            if !state.subscription_exists(subscription_id) {
2064                session_error!(
2065                    self,
2066                    "modify_monitored_items, subscription id {} does not exist",
2067                    subscription_id
2068                );
2069                return Err(Error::new(
2070                    StatusCode::BadSubscriptionIdInvalid,
2071                    format!(
2072                        "modify_monitored_items, subscription id {} does not exist",
2073                        subscription_id
2074                    ),
2075                ));
2076            }
2077        }
2078        let id_and_filter: Vec<(u32, ExtensionObject)> = items_to_modify
2079            .iter()
2080            .map(|i| (i.monitored_item_id, i.requested_parameters.filter.clone()))
2081            .collect();
2082        let results = ModifyMonitoredItems::new(subscription_id, self)
2083            .timestamps_to_return(timestamps_to_return)
2084            .items_to_modify(items_to_modify.to_vec())
2085            .send(&self.channel)
2086            .await?
2087            .results
2088            .unwrap_or_default();
2089
2090        let items_to_modify = id_and_filter
2091            .iter()
2092            .zip(results.iter())
2093            .map(|((id, requested_filter), r)| {
2094                let filter = if r.filter_result.is_null() {
2095                    requested_filter.clone()
2096                } else {
2097                    r.filter_result.clone()
2098                };
2099                ModifyMonitoredItem {
2100                    id: *id,
2101                    queue_size: r.revised_queue_size,
2102                    sampling_interval: r.revised_sampling_interval,
2103                    filter,
2104                }
2105            })
2106            .collect::<Vec<ModifyMonitoredItem>>();
2107        {
2108            let mut subscription_state = trace_lock!(self.subscription_state);
2109            subscription_state.modify_monitored_items(subscription_id, &items_to_modify);
2110        }
2111
2112        Ok(results)
2113    }
2114
2115    /// Sets the monitoring mode on one or more monitored items by sending a [`SetMonitoringModeRequest`]
2116    /// to the server.
2117    ///
2118    /// See OPC UA Part 4 - Services 5.12.4 for complete description of the service and error responses.
2119    ///
2120    /// # Arguments
2121    ///
2122    /// * `subscription_id` - the subscription identifier containing the monitored items to be modified.
2123    /// * `monitoring_mode` - the monitored mode to apply to the monitored items
2124    /// * `monitored_item_ids` - the monitored items to be modified
2125    ///
2126    /// # Returns
2127    ///
2128    /// * `Ok(Vec<StatusCode>)` - Individual result for each monitored item.
2129    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
2130    ///
2131    pub async fn set_monitoring_mode(
2132        &self,
2133        subscription_id: u32,
2134        monitoring_mode: MonitoringMode,
2135        monitored_item_ids: &[u32],
2136    ) -> Result<Vec<StatusCode>, Error> {
2137        {
2138            let state = trace_lock!(self.subscription_state);
2139            if !state.subscription_exists(subscription_id) {
2140                session_error!(
2141                    self,
2142                    "set_monitoring_mode, subscription id {} does not exist",
2143                    subscription_id
2144                );
2145                return Err(Error::new(
2146                    StatusCode::BadSubscriptionIdInvalid,
2147                    format!(
2148                        "set_monitoring_mode, subscription id {} does not exist",
2149                        subscription_id
2150                    ),
2151                ));
2152            }
2153        }
2154        let results = SetMonitoringMode::new(subscription_id, monitoring_mode, self)
2155            .monitored_item_ids(monitored_item_ids.to_vec())
2156            .send(&self.channel)
2157            .await?
2158            .results
2159            .unwrap_or_default();
2160
2161        let ok_ids: Vec<_> = monitored_item_ids
2162            .iter()
2163            .zip(results.iter())
2164            .filter(|(_, s)| s.is_good())
2165            .map(|(v, _)| *v)
2166            .collect();
2167        {
2168            let mut subscription_state = trace_lock!(self.subscription_state);
2169            subscription_state.set_monitoring_mode(subscription_id, &ok_ids, monitoring_mode);
2170        }
2171
2172        Ok(results)
2173    }
2174
2175    /// Sets a monitored item so it becomes the trigger that causes other monitored items to send
2176    /// change events in the same update. Sends a [`SetTriggeringRequest`] to the server.
2177    /// Note that `items_to_remove` is applied before `items_to_add`.
2178    ///
2179    /// See OPC UA Part 4 - Services 5.12.5 for complete description of the service and error responses.
2180    ///
2181    /// # Arguments
2182    ///
2183    /// * `subscription_id` - the subscription identifier containing the monitored item to be used as the trigger.
2184    /// * `monitored_item_id` - the monitored item that is the trigger.
2185    /// * `links_to_add` - zero or more items to be added to the monitored item's triggering list.
2186    /// * `items_to_remove` - zero or more items to be removed from the monitored item's triggering list.
2187    ///
2188    /// # Returns
2189    ///
2190    /// * `Ok((Option<Vec<StatusCode>>, Option<Vec<StatusCode>>))` - Individual result for each item added / removed for the SetTriggering call.
2191    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
2192    ///
2193    pub async fn set_triggering(
2194        &self,
2195        subscription_id: u32,
2196        triggering_item_id: u32,
2197        links_to_add: &[u32],
2198        links_to_remove: &[u32],
2199    ) -> Result<(Option<Vec<StatusCode>>, Option<Vec<StatusCode>>), Error> {
2200        {
2201            let state = trace_lock!(self.subscription_state);
2202            if !state.subscription_exists(subscription_id) {
2203                session_error!(
2204                    self,
2205                    "set_triggering, subscription id {} does not exist",
2206                    subscription_id
2207                );
2208                return Err(Error::new(
2209                    StatusCode::BadSubscriptionIdInvalid,
2210                    format!(
2211                        "set_triggering, subscription id {} does not exist",
2212                        subscription_id
2213                    ),
2214                ));
2215            }
2216        }
2217        let response = SetTriggering::new(subscription_id, triggering_item_id, self)
2218            .links_to_add(links_to_add.to_vec())
2219            .links_to_remove(links_to_remove.to_vec())
2220            .send(&self.channel)
2221            .await?;
2222
2223        let to_add_res = response.add_results.as_deref().unwrap_or(&[]);
2224        let to_remove_res = response.remove_results.as_deref().unwrap_or(&[]);
2225
2226        let ok_adds = to_add_res
2227            .iter()
2228            .zip(links_to_add)
2229            .filter(|(s, _)| s.is_good())
2230            .map(|(_, v)| v)
2231            .copied()
2232            .collect::<Vec<_>>();
2233        let ok_removes = to_remove_res
2234            .iter()
2235            .zip(links_to_remove)
2236            .filter(|(s, _)| s.is_good())
2237            .map(|(_, v)| v)
2238            .copied()
2239            .collect::<Vec<_>>();
2240
2241        // Update client side state
2242        let mut subscription_state = trace_lock!(self.subscription_state);
2243        subscription_state.set_triggering(
2244            subscription_id,
2245            triggering_item_id,
2246            &ok_adds,
2247            &ok_removes,
2248        );
2249        Ok((response.add_results, response.remove_results))
2250    }
2251
2252    /// Deletes monitored items from a subscription by sending a [`DeleteMonitoredItemsRequest`] to the server.
2253    ///
2254    /// See OPC UA Part 4 - Services 5.12.6 for complete description of the service and error responses.
2255    ///
2256    /// # Arguments
2257    ///
2258    /// * `subscription_id` - The Server-assigned identifier for the Subscription that will report Notifications for this MonitoredItem.
2259    /// * `items_to_delete` - List of Server-assigned ids for the MonitoredItems to be deleted.
2260    ///
2261    /// # Returns
2262    ///
2263    /// * `Ok(Vec<StatusCode>)` - List of StatusCodes for the MonitoredItems to delete. The size and
2264    ///   order of the list matches the size and order of the `items_to_delete` request parameter.
2265    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
2266    ///
2267    pub async fn delete_monitored_items(
2268        &self,
2269        subscription_id: u32,
2270        items_to_delete: &[u32],
2271    ) -> Result<Vec<StatusCode>, Error> {
2272        {
2273            let state = trace_lock!(self.subscription_state);
2274            if !state.subscription_exists(subscription_id) {
2275                session_error!(
2276                    self,
2277                    "delete_monitored_items, subscription id {} does not exist",
2278                    subscription_id
2279                );
2280                return Err(Error::new(
2281                    StatusCode::BadSubscriptionIdInvalid,
2282                    format!(
2283                        "delete_monitored_items, subscription id {} does not exist",
2284                        subscription_id
2285                    ),
2286                ));
2287            }
2288        }
2289        let response = DeleteMonitoredItems::new(subscription_id, self)
2290            .items_to_delete(items_to_delete.to_vec())
2291            .send(&self.channel)
2292            .await?
2293            .results
2294            .unwrap_or_default();
2295        let mut subscription_state = trace_lock!(self.subscription_state);
2296        subscription_state.delete_monitored_items(subscription_id, items_to_delete);
2297        Ok(response)
2298    }
2299
2300    pub(crate) fn next_publish_time(&self, set_last_publish: bool) -> Option<Instant> {
2301        let mut subscription_state = trace_lock!(self.subscription_state);
2302        if set_last_publish {
2303            subscription_state.set_last_publish();
2304        }
2305        subscription_state.next_publish_time()
2306    }
2307
2308    /// Send a publish request, returning `true` if the session should send a new request
2309    /// immediately.
2310    pub(crate) async fn publish(&self) -> Result<bool, Error> {
2311        let acks = {
2312            let mut subscription_state = trace_lock!(self.subscription_state);
2313            let acks = subscription_state.take_acknowledgements();
2314            if !acks.is_empty() {
2315                Some(acks)
2316            } else {
2317                None
2318            }
2319        };
2320
2321        match Publish::new(self)
2322            .acks(acks.clone().unwrap_or_default())
2323            .send(&self.channel)
2324            .await
2325        {
2326            Ok(r) => {
2327                if let (Some(sent), Some(results)) = (acks.as_ref(), r.results.as_ref()) {
2328                    for (ack, status) in sent.iter().zip(results.iter()) {
2329                        if !status.is_good() && *status != StatusCode::BadSequenceNumberUnknown {
2330                            tracing::warn!(
2331                                "Server rejected ack for subscription {} seq {}: {status}",
2332                                ack.subscription_id,
2333                                ack.sequence_number,
2334                            );
2335                        }
2336                    }
2337                }
2338                let mut subscription_state = trace_lock!(self.subscription_state);
2339                subscription_state.handle_notification(r.subscription_id, r.notification_message);
2340                Ok(r.more_notifications)
2341            }
2342            Err(e) => {
2343                if let Some(acks) = acks {
2344                    let mut subscription_state = trace_lock!(self.subscription_state);
2345                    subscription_state.re_queue_acknowledgements(acks);
2346                }
2347                Err(e)
2348            }
2349        }
2350    }
2351
2352    /// Send a request to re-publish an unacknowledged notification message from the server.
2353    ///
2354    /// If this succeeds, the session will automatically acknowledge the notification in the next publish request.
2355    ///
2356    /// # Arguments
2357    ///
2358    /// * `subscription_id` - The Server-assigned identifier for the Subscription to republish from.
2359    /// * `sequence_number` - Sequence number to re-publish.
2360    ///
2361    /// # Returns
2362    ///
2363    /// * `Ok(NotificationMessage)` - Re-published notification message.
2364    /// * `Err(Error)` - Request failed, [Status code](StatusCode) is the reason for failure.
2365    ///
2366    pub async fn republish(
2367        &self,
2368        subscription_id: u32,
2369        sequence_number: u32,
2370    ) -> Result<NotificationMessage, Error> {
2371        let res = Republish::new(subscription_id, sequence_number, self)
2372            .send(&self.channel)
2373            .await?;
2374
2375        {
2376            let mut lck = trace_lock!(self.subscription_state);
2377            lck.add_acknowledgement(subscription_id, sequence_number);
2378        }
2379
2380        Ok(res.notification_message)
2381    }
2382
2383    /// This code attempts to take the existing subscriptions created by a previous session and
2384    /// either transfer them to this session, or construct them from scratch.
2385    pub(crate) async fn transfer_subscriptions_from_old_session(&self) {
2386        let subscription_ids = {
2387            let mut subscription_state = trace_lock!(self.subscription_state);
2388            let _stale_acks = subscription_state.take_acknowledgements();
2389            subscription_state.subscription_ids()
2390        };
2391
2392        let Some(subscription_ids) = subscription_ids else {
2393            return;
2394        };
2395
2396        // Start by getting the subscription ids
2397        // Try to use TransferSubscriptions to move subscriptions_ids over. If this
2398        // works then there is nothing else to do.
2399        let mut subscription_ids_to_recreate =
2400            subscription_ids.iter().copied().collect::<HashSet<u32>>();
2401        if let Ok(transfer_results) = self.transfer_subscriptions(&subscription_ids, true).await {
2402            session_debug!(self, "transfer_results = {:?}", transfer_results);
2403            transfer_results.iter().enumerate().for_each(|(i, r)| {
2404                if r.status_code.is_good() {
2405                    // Subscription was transferred so it does not need to be recreated
2406                    subscription_ids_to_recreate.remove(&subscription_ids[i]);
2407                }
2408            });
2409        }
2410
2411        // But if it didn't work, then some or all subscriptions have to be remade.
2412        if !subscription_ids_to_recreate.is_empty() {
2413            session_warn!(self, "Some or all of the existing subscriptions could not be transferred and must be created manually");
2414        }
2415
2416        for subscription_id in subscription_ids_to_recreate {
2417            session_debug!(self, "Recreating subscription {}", subscription_id);
2418
2419            let deleted_subscription = {
2420                let mut subscription_state = trace_lock!(self.subscription_state);
2421                subscription_state.delete_subscription(subscription_id)
2422            };
2423
2424            let Some(subscription) = deleted_subscription else {
2425                session_warn!(
2426                    self,
2427                    "Subscription removed from session while transfer in progress"
2428                );
2429                continue;
2430            };
2431
2432            let Ok(subscription_id) = self
2433                .create_subscription_inner(
2434                    subscription.publishing_interval,
2435                    subscription.lifetime_count,
2436                    subscription.max_keep_alive_count,
2437                    subscription.max_notifications_per_publish,
2438                    subscription.publishing_enabled,
2439                    subscription.priority,
2440                    subscription.callback,
2441                )
2442                .await
2443            else {
2444                session_warn!(
2445                    self,
2446                    "Could not create a subscription from the existing subscription {}",
2447                    subscription_id
2448                );
2449                continue;
2450            };
2451
2452            let items_to_create = subscription
2453                .monitored_items
2454                .values()
2455                .map(|item| MonitoredItemCreateRequest {
2456                    item_to_monitor: item.item_to_monitor().clone(),
2457                    monitoring_mode: item.monitoring_mode,
2458                    requested_parameters: MonitoringParameters {
2459                        client_handle: item.client_handle(),
2460                        sampling_interval: item.sampling_interval(),
2461                        filter: item.filter.clone(),
2462                        queue_size: item.queue_size() as u32,
2463                        discard_oldest: item.discard_oldest(),
2464                    },
2465                })
2466                .collect::<Vec<MonitoredItemCreateRequest>>();
2467
2468            let mut iter = items_to_create.into_iter();
2469
2470            loop {
2471                let chunk = (&mut iter)
2472                    .take(self.recreate_monitored_items_chunk)
2473                    .collect::<Vec<_>>();
2474
2475                if chunk.is_empty() {
2476                    break;
2477                }
2478
2479                let _ = self
2480                    .create_monitored_items(subscription_id, TimestampsToReturn::Both, chunk)
2481                    .await;
2482            }
2483
2484            for item in subscription.monitored_items.values() {
2485                let triggered_items = item.triggered_items();
2486                if !triggered_items.is_empty() {
2487                    let links_to_add = triggered_items.iter().copied().collect::<Vec<u32>>();
2488                    if let Err(e) = self
2489                        .set_triggering(subscription_id, item.id(), links_to_add.as_slice(), &[])
2490                        .await
2491                    {
2492                        session_warn!(
2493                            self,
2494                            "Failed to re-apply triggering links for monitored item {} on recreated subscription {}: {e}",
2495                            item.id(),
2496                            subscription_id,
2497                        );
2498                    }
2499                }
2500            }
2501        }
2502    }
2503}