opcua_client/session/services/subscriptions/
callbacks.rs1use opcua_types::{
2 match_extension_object_owned, DataChangeNotification, DataValue, EventNotificationList,
3 NotificationMessage, StatusChangeNotification, Variant,
4};
5
6use crate::{session::services::subscriptions::MonitoredItemMap, MonitoredItem};
7
8pub trait OnSubscriptionNotificationCore: Send + Sync {
12 fn on_subscription_notification(
14 &mut self,
15 notification: NotificationMessage,
16 monitored_items: MonitoredItemMap<'_>,
17 );
18}
19
20impl<T> OnSubscriptionNotificationCore for T
21where
22 T: OnSubscriptionNotification + Send + Sync,
23{
24 fn on_subscription_notification(
25 &mut self,
26 notification: NotificationMessage,
27 monitored_items: MonitoredItemMap<'_>,
28 ) {
29 let Some(notifications) = notification.notification_data else {
30 return;
31 };
32
33 for obj in notifications {
34 match_extension_object_owned!(obj,
35 v: DataChangeNotification => {
36 for notif in v.monitored_items.into_iter().flatten() {
37 let item = monitored_items.get(notif.client_handle);
38
39 if let Some(item) = item {
40 self.on_data_value(notif.value, item);
41 } else {
42 tracing::warn!("Received notification for unknown monitored item {}", notif.client_handle);
43 }
44 }
45 },
46 v: EventNotificationList => {
47 for notif in v.events.into_iter().flatten() {
48 let item = monitored_items.get(notif.client_handle);
49
50 if let Some(item) = item {
51 self.on_event(notif.event_fields, item);
52 } else {
53 tracing::warn!("Received event for unknown monitored item {}", notif.client_handle);
54 }
55 }
56 },
57 v: StatusChangeNotification => {
58 self.on_subscription_status_change(v);
59 }
60 )
61 }
62 }
63}
64
65pub trait OnSubscriptionNotification: Send + Sync {
69 #[allow(unused)]
71 fn on_subscription_status_change(&mut self, notification: StatusChangeNotification) {}
72
73 #[allow(unused)]
75 fn on_data_value(&mut self, notification: DataValue, item: &MonitoredItem) {}
76
77 #[allow(unused)]
79 fn on_event(&mut self, event_fields: Option<Vec<Variant>>, item: &MonitoredItem) {}
80}
81
82type StatusChangeCallbackFun = dyn FnMut(StatusChangeNotification) + Send + Sync;
83type DataChangeCallbackFun = dyn FnMut(DataValue, &MonitoredItem) + Send + Sync;
84type EventCallbackFun = dyn FnMut(Option<Vec<Variant>>, &MonitoredItem) + Send + Sync;
85
86pub struct SubscriptionCallbacks {
88 status_change: Box<StatusChangeCallbackFun>,
89 data_value: Box<DataChangeCallbackFun>,
90 event: Box<EventCallbackFun>,
91}
92
93impl SubscriptionCallbacks {
94 pub fn new(
102 status_change: impl FnMut(StatusChangeNotification) + Send + Sync + 'static,
103 data_value: impl FnMut(DataValue, &MonitoredItem) + Send + Sync + 'static,
104 event: impl FnMut(Option<Vec<Variant>>, &MonitoredItem) + Send + Sync + 'static,
105 ) -> Self {
106 Self {
107 status_change: Box::new(status_change) as Box<StatusChangeCallbackFun>,
108 data_value: Box::new(data_value) as Box<DataChangeCallbackFun>,
109 event: Box::new(event) as Box<EventCallbackFun>,
110 }
111 }
112}
113
114impl OnSubscriptionNotification for SubscriptionCallbacks {
115 fn on_subscription_status_change(&mut self, notification: StatusChangeNotification) {
116 (self.status_change)(notification);
117 }
118
119 fn on_data_value(&mut self, notification: DataValue, item: &MonitoredItem) {
120 (self.data_value)(notification, item);
121 }
122
123 fn on_event(&mut self, event_fields: Option<Vec<Variant>>, item: &MonitoredItem) {
124 (self.event)(event_fields, item);
125 }
126}
127
128pub struct DataChangeCallback {
130 data_value: Box<DataChangeCallbackFun>,
131}
132
133impl DataChangeCallback {
134 pub fn new(data_value: impl FnMut(DataValue, &MonitoredItem) + Send + Sync + 'static) -> Self {
140 Self {
141 data_value: Box::new(data_value)
142 as Box<dyn FnMut(DataValue, &MonitoredItem) + Send + Sync>,
143 }
144 }
145}
146
147impl OnSubscriptionNotification for DataChangeCallback {
148 fn on_data_value(&mut self, notification: DataValue, item: &MonitoredItem) {
149 (self.data_value)(notification, item);
150 }
151}
152
153pub struct EventCallback {
155 event: Box<EventCallbackFun>,
156}
157
158impl EventCallback {
159 pub fn new(
165 event: impl FnMut(Option<Vec<Variant>>, &MonitoredItem) + Send + Sync + 'static,
166 ) -> Self {
167 Self {
168 event: Box::new(event)
169 as Box<dyn FnMut(Option<Vec<Variant>>, &MonitoredItem) + Send + Sync>,
170 }
171 }
172}
173
174impl OnSubscriptionNotification for EventCallback {
175 fn on_event(&mut self, event_fields: Option<Vec<Variant>>, item: &MonitoredItem) {
176 (self.event)(event_fields, item);
177 }
178}