Skip to main content

opcua/server/address_space/
variable.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2022 Adam Lock
4
5//! Contains the implementation of `Variable` and `VariableBuilder`.
6
7use std::convert::{Into, TryFrom};
8use std::sync::Arc;
9
10use crate::sync::*;
11use crate::types::service_types::VariableAttributes;
12
13use crate::server::{
14    address_space::{
15        base::Base,
16        node::{Node, NodeBase},
17        AccessLevel, UserAccessLevel,
18    },
19    callbacks::{AttributeGetter, AttributeSetter},
20};
21
22// This is a builder object for constructing variable nodes programmatically.
23
24node_builder_impl!(VariableBuilder, Variable);
25node_builder_impl_component_of!(VariableBuilder);
26node_builder_impl_property_of!(VariableBuilder);
27
28impl VariableBuilder {
29    /// Sets the value of the variable.
30    pub fn value<V>(mut self, value: V) -> Self
31    where
32        V: Into<Variant>,
33    {
34        let _ = self.node.set_value(NumericRange::None, value);
35        self
36    }
37
38    /// Sets the data type of the variable.
39    pub fn data_type<T>(mut self, data_type: T) -> Self
40    where
41        T: Into<NodeId>,
42    {
43        self.node.set_data_type(data_type);
44        self
45    }
46
47    /// Sets the historizing flag for the variable.
48    pub fn historizing(mut self, historizing: bool) -> Self {
49        self.node.set_historizing(historizing);
50        self
51    }
52
53    /// Sets the access level for the variable.
54    pub fn access_level(mut self, access_level: AccessLevel) -> Self {
55        self.node.set_access_level(access_level);
56        self
57    }
58
59    /// Sets the user access level for the variable.
60    pub fn user_access_level(mut self, user_access_level: UserAccessLevel) -> Self {
61        self.node.set_user_access_level(user_access_level);
62        self
63    }
64
65    /// Sets the value rank for the variable.
66    pub fn value_rank(mut self, value_rank: i32) -> Self {
67        self.node.set_value_rank(value_rank);
68        self
69    }
70
71    /// Sets the array dimensions for the variable.
72    pub fn array_dimensions(mut self, array_dimensions: &[u32]) -> Self {
73        self.node.set_array_dimensions(array_dimensions);
74        self
75    }
76
77    /// Makes the variable writable (by default it isn't)
78    pub fn writable(mut self) -> Self {
79        self.node
80            .set_user_access_level(self.node.user_access_level() | UserAccessLevel::CURRENT_WRITE);
81        self.node
82            .set_access_level(self.node.access_level() | AccessLevel::CURRENT_WRITE);
83        self
84    }
85
86    /// Makes the variable history-readable
87    pub fn history_readable(mut self) -> Self {
88        self.node
89            .set_user_access_level(self.node.user_access_level() | UserAccessLevel::HISTORY_READ);
90        self.node
91            .set_access_level(self.node.access_level() | AccessLevel::HISTORY_READ);
92        self
93    }
94
95    /// Makes the variable history-updateable
96    pub fn history_updatable(mut self) -> Self {
97        self.node
98            .set_user_access_level(self.node.user_access_level() | UserAccessLevel::HISTORY_WRITE);
99        self.node
100            .set_access_level(self.node.access_level() | AccessLevel::HISTORY_WRITE);
101        self
102    }
103
104    /// Sets the minimum sampling interval for the variable.
105    pub fn minimum_sampling_interval(mut self, minimum_sampling_interval: f64) -> Self {
106        self.node
107            .set_minimum_sampling_interval(minimum_sampling_interval);
108        self
109    }
110
111    /// Sets a value getter function for the variable. Whenever the value of a variable
112    /// needs to be fetched (e.g. from a monitored item subscription), this trait will be called
113    /// to get the value.
114    pub fn value_getter(mut self, getter: Arc<Mutex<dyn AttributeGetter + Send>>) -> Self {
115        self.node.set_value_getter(getter);
116        self
117    }
118
119    /// Sets a value setter function for the variable. Whenever the value of a variable is set via
120    /// a service, this trait will be called to set the value. It is up to the implementation
121    /// to decide what to do if that happens.
122    pub fn value_setter(mut self, setter: Arc<Mutex<dyn AttributeSetter + Send>>) -> Self {
123        self.node.set_value_setter(setter);
124        self
125    }
126
127    /// Add a reference to the variable indicating it has a type of another node.
128    pub fn has_type_definition<T>(self, type_id: T) -> Self
129    where
130        T: Into<NodeId>,
131    {
132        self.reference(
133            type_id,
134            ReferenceTypeId::HasTypeDefinition,
135            ReferenceDirection::Forward,
136        )
137    }
138
139    /// Add a reference to the variable indicating it has a modelling rule of another node.
140    pub fn has_modelling_rule<T>(self, type_id: T) -> Self
141    where
142        T: Into<NodeId>,
143    {
144        self.reference(
145            type_id,
146            ReferenceTypeId::HasModellingRule,
147            ReferenceDirection::Forward,
148        )
149    }
150}
151
152// Note we use derivative builder macro so we can skip over the value getter / setter
153
154/// A `Variable` is a type of node within the `AddressSpace`.
155#[derive(Derivative)]
156#[derivative(Debug)]
157pub struct Variable {
158    base: Base,
159    data_type: NodeId,
160    historizing: bool,
161    value_rank: i32,
162    value: DataValue,
163    access_level: u8,
164    user_access_level: u8,
165    array_dimensions: Option<Vec<u32>>,
166    minimum_sampling_interval: Option<f64>,
167    #[derivative(Debug = "ignore")]
168    value_setter: Option<Arc<Mutex<dyn AttributeSetter + Send>>>,
169    #[derivative(Debug = "ignore")]
170    value_getter: Option<Arc<Mutex<dyn AttributeGetter + Send>>>,
171}
172
173impl Default for Variable {
174    fn default() -> Self {
175        Self {
176            base: Base::new(NodeClass::Variable, &NodeId::null(), "", ""),
177            data_type: NodeId::null(),
178            historizing: false,
179            value_rank: -1,
180            value: Variant::Empty.into(),
181            access_level: UserAccessLevel::CURRENT_READ.bits(),
182            user_access_level: AccessLevel::CURRENT_READ.bits(),
183            array_dimensions: None,
184            minimum_sampling_interval: None,
185            value_getter: None,
186            value_setter: None,
187        }
188    }
189}
190
191node_base_impl!(Variable);
192
193impl Node for Variable {
194    fn get_attribute_max_age(
195        &self,
196        timestamps_to_return: TimestampsToReturn,
197        attribute_id: AttributeId,
198        index_range: NumericRange,
199        data_encoding: &QualifiedName,
200        max_age: f64,
201    ) -> Option<DataValue> {
202        /* TODO for Variables derived from the Structure data type, the AttributeId::Value should check
203        data encoding and return the value encoded according "Default Binary", "Default XML" or "Default JSON" (OPC UA 1.04).
204        */
205        match attribute_id {
206            // Mandatory attributes
207            AttributeId::Value => {
208                Some(self.value(timestamps_to_return, index_range, data_encoding, max_age))
209            }
210            AttributeId::DataType => Some(self.data_type().into()),
211            AttributeId::Historizing => Some(self.historizing().into()),
212            AttributeId::ValueRank => Some(self.value_rank().into()),
213            AttributeId::AccessLevel => Some(self.access_level().bits().into()),
214            AttributeId::UserAccessLevel => Some(self.user_access_level().bits().into()),
215            // Optional attributes
216            AttributeId::ArrayDimensions => {
217                self.array_dimensions().map(|v| Variant::from(v).into())
218            }
219            AttributeId::MinimumSamplingInterval => {
220                self.minimum_sampling_interval().map(|v| v.into())
221            }
222            _ => self.base.get_attribute_max_age(
223                timestamps_to_return,
224                attribute_id,
225                index_range,
226                data_encoding,
227                max_age,
228            ),
229        }
230    }
231
232    fn set_attribute(
233        &mut self,
234        attribute_id: AttributeId,
235        value: Variant,
236    ) -> Result<(), StatusCode> {
237        match attribute_id {
238            AttributeId::DataType => {
239                if let Variant::NodeId(v) = value {
240                    self.set_data_type(*v);
241                    Ok(())
242                } else {
243                    Err(StatusCode::BadTypeMismatch)
244                }
245            }
246            AttributeId::Historizing => {
247                if let Variant::Boolean(v) = value {
248                    self.set_historizing(v);
249                    Ok(())
250                } else {
251                    Err(StatusCode::BadTypeMismatch)
252                }
253            }
254            AttributeId::ValueRank => {
255                if let Variant::Int32(v) = value {
256                    self.set_value_rank(v);
257                    Ok(())
258                } else {
259                    Err(StatusCode::BadTypeMismatch)
260                }
261            }
262            AttributeId::Value => {
263                // Call set_value directly
264                self.set_value(NumericRange::None, value)
265            }
266            AttributeId::AccessLevel => {
267                if let Variant::Byte(v) = value {
268                    self.set_access_level(AccessLevel::from_bits_truncate(v));
269                    Ok(())
270                } else {
271                    Err(StatusCode::BadTypeMismatch)
272                }
273            }
274            AttributeId::UserAccessLevel => {
275                if let Variant::Byte(v) = value {
276                    self.set_user_access_level(UserAccessLevel::from_bits_truncate(v));
277                    Ok(())
278                } else {
279                    Err(StatusCode::BadTypeMismatch)
280                }
281            }
282            AttributeId::ArrayDimensions => {
283                let array_dimensions = <Vec<u32>>::try_from(&value);
284                if let Ok(array_dimensions) = array_dimensions {
285                    self.set_array_dimensions(&array_dimensions);
286                    Ok(())
287                } else {
288                    Err(StatusCode::BadTypeMismatch)
289                }
290            }
291            AttributeId::MinimumSamplingInterval => {
292                if let Variant::Double(v) = value {
293                    self.set_minimum_sampling_interval(v);
294                    Ok(())
295                } else {
296                    Err(StatusCode::BadTypeMismatch)
297                }
298            }
299            _ => self.base.set_attribute(attribute_id, value),
300        }
301    }
302}
303
304impl Variable {
305    /// Creates a new variable. Note that data type, value rank and historizing are mandatory
306    /// attributes of the Variable but not required by the constructor. The data type and value rank
307    /// are inferred from the value. Historizing is not supported so is always false. If the
308    /// inferred types for data type or value rank are wrong, they may be explicitly set, or
309    /// call `new_data_value()` instead.
310    pub fn new<R, S, V>(node_id: &NodeId, browse_name: R, display_name: S, value: V) -> Variable
311    where
312        R: Into<QualifiedName>,
313        S: Into<LocalizedText>,
314        V: Into<Variant>,
315    {
316        let value = value.into();
317        let data_type = value.scalar_data_type().or_else(|| value.array_data_type());
318        if let Some(data_type) = data_type {
319            Variable::new_data_value(
320                node_id,
321                browse_name,
322                display_name,
323                data_type,
324                None,
325                None,
326                value,
327            )
328        } else {
329            panic!("Data type cannot be inferred from the value, use another constructor such as new_data_value")
330        }
331    }
332
333    pub fn from_attributes<S>(
334        node_id: &NodeId,
335        browse_name: S,
336        attributes: VariableAttributes,
337    ) -> Result<Self, ()>
338    where
339        S: Into<QualifiedName>,
340    {
341        let mandatory_attributes = AttributesMask::DISPLAY_NAME
342            | AttributesMask::ACCESS_LEVEL
343            | AttributesMask::USER_ACCESS_LEVEL
344            | AttributesMask::DATA_TYPE
345            | AttributesMask::HISTORIZING
346            | AttributesMask::VALUE
347            | AttributesMask::VALUE_RANK;
348        let mask = AttributesMask::from_bits(attributes.specified_attributes).ok_or(())?;
349        if mask.contains(mandatory_attributes) {
350            let mut node = Self::new_data_value(
351                node_id,
352                browse_name,
353                attributes.display_name,
354                attributes.data_type,
355                None,
356                None,
357                attributes.value,
358            );
359            node.set_value_rank(attributes.value_rank);
360            node.set_historizing(attributes.historizing);
361            node.set_access_level(AccessLevel::from_bits_truncate(attributes.access_level));
362            node.set_user_access_level(UserAccessLevel::from_bits_truncate(
363                attributes.user_access_level,
364            ));
365
366            if mask.contains(AttributesMask::DESCRIPTION) {
367                node.set_description(attributes.description);
368            }
369            if mask.contains(AttributesMask::WRITE_MASK) {
370                node.set_write_mask(WriteMask::from_bits_truncate(attributes.write_mask));
371            }
372            if mask.contains(AttributesMask::USER_WRITE_MASK) {
373                node.set_user_write_mask(WriteMask::from_bits_truncate(attributes.user_write_mask));
374            }
375            if mask.contains(AttributesMask::ARRAY_DIMENSIONS) {
376                node.set_array_dimensions(attributes.array_dimensions.unwrap().as_slice());
377            }
378            if mask.contains(AttributesMask::MINIMUM_SAMPLING_INTERVAL) {
379                node.set_minimum_sampling_interval(attributes.minimum_sampling_interval);
380            }
381            Ok(node)
382        } else {
383            error!("Variable cannot be created from attributes - missing mandatory values");
384            Err(())
385        }
386    }
387
388    /// Constructs a new variable with the specified id, name, type and value
389    pub fn new_data_value<S, R, N, V>(
390        node_id: &NodeId,
391        browse_name: R,
392        display_name: S,
393        data_type: N,
394        value_rank: Option<i32>,
395        array_dimensions: Option<u32>,
396        value: V,
397    ) -> Variable
398    where
399        R: Into<QualifiedName>,
400        S: Into<LocalizedText>,
401        N: Into<NodeId>,
402        V: Into<Variant>,
403    {
404        let value = value.into();
405        let array_dimensions = if let Some(array_dimensions) = array_dimensions {
406            Some(vec![array_dimensions])
407        } else {
408            match value {
409                Variant::Array(ref array) => {
410                    if let Some(ref array_dimensions) = array.dimensions {
411                        // Multidimensional arrays encode/decode dimensions with Int32 in Part 6, but arrayDimensions in Part 3
412                        // wants them as u32. Go figure... So convert Int32 to u32
413                        Some(
414                            array_dimensions
415                                .iter()
416                                .map(|v| *v as u32)
417                                .collect::<Vec<u32>>(),
418                        )
419                    } else {
420                        Some(vec![array.values.len() as u32])
421                    }
422                }
423                _ => None,
424            }
425        };
426
427        let value_rank = if let Some(value_rank) = value_rank {
428            value_rank
429        } else if let Some(ref array_dimensions) = array_dimensions {
430            array_dimensions.len() as i32
431        } else {
432            -1
433        };
434
435        let builder = VariableBuilder::new(node_id, browse_name, display_name)
436            .user_access_level(UserAccessLevel::CURRENT_READ)
437            .access_level(AccessLevel::CURRENT_READ)
438            .data_type(data_type)
439            .historizing(false)
440            .value_rank(value_rank)
441            .value(value);
442
443        // Set the array info
444        let builder = if let Some(ref array_dimensions) = array_dimensions {
445            builder.array_dimensions(array_dimensions.as_slice())
446        } else {
447            builder
448        };
449        builder.build()
450    }
451
452    pub fn is_valid(&self) -> bool {
453        !self.data_type.is_null() && self.base.is_valid()
454    }
455
456    pub fn value(
457        &self,
458        timestamps_to_return: TimestampsToReturn,
459        index_range: NumericRange,
460        data_encoding: &QualifiedName,
461        max_age: f64,
462    ) -> DataValue {
463        use std::i32;
464
465        if let Some(ref value_getter) = self.value_getter {
466            let mut value_getter = value_getter.lock();
467            value_getter
468                .get(
469                    &self.node_id(),
470                    timestamps_to_return,
471                    AttributeId::Value,
472                    index_range,
473                    data_encoding,
474                    max_age,
475                )
476                .unwrap_or_else(|status_code| {
477                    let mut value = DataValue::default();
478                    value.status = Some(status_code);
479                    Some(value)
480                })
481                .unwrap_or_default()
482        } else {
483            let data_value = &self.value;
484            let mut result = DataValue {
485                server_picoseconds: data_value.server_picoseconds,
486                server_timestamp: data_value.server_timestamp,
487                source_picoseconds: data_value.source_picoseconds,
488                source_timestamp: data_value.source_timestamp,
489                value: None,
490                status: None,
491            };
492
493            // Get the value
494            if let Some(ref value) = data_value.value {
495                match value.range_of(index_range) {
496                    Ok(value) => {
497                        result.value = Some(value);
498                        result.status = data_value.status;
499                    }
500                    Err(err) => {
501                        result.status = Some(err);
502                    }
503                }
504            }
505            if max_age > 0.0 && max_age <= i32::MAX as f64 {
506                // Update the server timestamp to now as a "best effort" attempt to get the latest value
507                result.server_timestamp = Some(DateTime::now());
508            }
509            result
510        }
511    }
512
513    /// Sets the variable's `Variant` value. The timestamps for the change are updated to now.
514    pub fn set_value<V>(&mut self, index_range: NumericRange, value: V) -> Result<(), StatusCode>
515    where
516        V: Into<Variant>,
517    {
518        let mut value = value.into();
519
520        // A special case is required here for when the variable is a single dimension
521        // byte array and the value is a ByteString.
522        match self.value_rank {
523            -3 | -2 | 1 => {
524                if self.data_type == DataTypeId::Byte.into() {
525                    if let Variant::ByteString(_) = value {
526                        // Convert the value from a byte string to a byte array
527                        value = value.to_byte_array()?;
528                    }
529                }
530            }
531            _ => { /* DO NOTHING */ }
532        };
533
534        // The value is set to the value getter
535        if let Some(ref value_setter) = self.value_setter {
536            let mut value_setter = value_setter.lock();
537            value_setter.set(
538                &self.node_id(),
539                AttributeId::Value,
540                index_range,
541                value.into(),
542            )
543        } else {
544            let now = DateTime::now();
545            if index_range.has_range() {
546                self.set_value_range(value, index_range, StatusCode::Good, &now, &now)
547            } else {
548                self.set_value_direct(value, StatusCode::Good, &now, &now)
549            }
550        }
551    }
552
553    // Set a range value
554    pub fn set_value_range(
555        &mut self,
556        value: Variant,
557        index_range: NumericRange,
558        status_code: StatusCode,
559        server_timestamp: &DateTime,
560        source_timestamp: &DateTime,
561    ) -> Result<(), StatusCode> {
562        match self.value.value {
563            Some(ref mut full_value) => {
564                // Overwrite a partial section of the value
565                full_value.set_range_of(index_range, &value)?;
566                self.value.status = Some(status_code);
567                self.value.server_timestamp = Some(*server_timestamp);
568                self.value.source_timestamp = Some(*source_timestamp);
569                Ok(())
570            }
571            None => Err(StatusCode::BadIndexRangeInvalid),
572        }
573    }
574
575    /// Sets the variable's `DataValue`
576    pub fn set_value_direct<V>(
577        &mut self,
578        value: V,
579        status_code: StatusCode,
580        server_timestamp: &DateTime,
581        source_timestamp: &DateTime,
582    ) -> Result<(), StatusCode>
583    where
584        V: Into<Variant>,
585    {
586        self.value.value = Some(value.into());
587        self.value.status = Some(status_code);
588        self.value.server_timestamp = Some(*server_timestamp);
589        self.value.source_timestamp = Some(*source_timestamp);
590        Ok(())
591    }
592
593    /// Sets a getter function that will be called to get the value of this variable.
594    pub fn set_value_getter(&mut self, value_getter: Arc<Mutex<dyn AttributeGetter + Send>>) {
595        self.value_getter = Some(value_getter);
596    }
597
598    /// Sets a setter function that will be called to set the value of this variable.
599    pub fn set_value_setter(&mut self, value_setter: Arc<Mutex<dyn AttributeSetter + Send>>) {
600        self.value_setter = Some(value_setter);
601    }
602
603    /// Gets the minimum sampling interval, if the attribute was set
604    pub fn minimum_sampling_interval(&self) -> Option<f64> {
605        self.minimum_sampling_interval
606    }
607
608    /// Sets the minimum sampling interval
609    ///
610    /// Specifies in milliseconds how fast the server can reasonably sample the value for changes
611    ///
612    /// The value 0 means server is to monitor the value continuously. The value -1 means indeterminate.
613    pub fn set_minimum_sampling_interval(&mut self, minimum_sampling_interval: f64) {
614        self.minimum_sampling_interval = Some(minimum_sampling_interval);
615    }
616
617    /// Test if the variable is readable. This will be called by services before getting the value
618    /// of the node.
619    pub fn is_readable(&self) -> bool {
620        self.access_level().contains(AccessLevel::CURRENT_READ)
621    }
622
623    /// Test if the variable is writable. This will be called by services before setting the value
624    /// on the node.
625    pub fn is_writable(&self) -> bool {
626        self.access_level().contains(AccessLevel::CURRENT_WRITE)
627    }
628
629    /// Sets the variable writable state.
630    pub fn set_writable(&mut self, writable: bool) {
631        let mut access_level = self.access_level();
632        if writable {
633            access_level.insert(AccessLevel::CURRENT_WRITE);
634        } else {
635            access_level.remove(AccessLevel::CURRENT_WRITE);
636        }
637        self.set_access_level(access_level);
638    }
639
640    /// Returns the access level of the variable.
641    pub fn access_level(&self) -> AccessLevel {
642        AccessLevel::from_bits_truncate(self.access_level)
643    }
644
645    /// Sets the access level of the variable.
646    pub fn set_access_level(&mut self, access_level: AccessLevel) {
647        self.access_level = access_level.bits();
648    }
649
650    /// Test if the variable is user readable.
651    pub fn is_user_readable(&self) -> bool {
652        self.user_access_level()
653            .contains(UserAccessLevel::CURRENT_READ)
654    }
655
656    /// Test if the variable is user writable.
657    pub fn is_user_writable(&self) -> bool {
658        self.user_access_level()
659            .contains(UserAccessLevel::CURRENT_WRITE)
660    }
661
662    /// Returns the user access level of the variable.
663    pub fn user_access_level(&self) -> UserAccessLevel {
664        UserAccessLevel::from_bits_truncate(self.user_access_level)
665    }
666
667    /// Set the user access level of the variable.
668    pub fn set_user_access_level(&mut self, user_access_level: UserAccessLevel) {
669        self.user_access_level = user_access_level.bits();
670    }
671
672    pub fn value_rank(&self) -> i32 {
673        self.value_rank
674    }
675
676    pub fn set_value_rank(&mut self, value_rank: i32) {
677        self.value_rank = value_rank;
678    }
679
680    pub fn historizing(&self) -> bool {
681        self.historizing
682    }
683
684    pub fn set_historizing(&mut self, historizing: bool) {
685        self.historizing = historizing;
686    }
687
688    pub fn array_dimensions(&self) -> Option<Vec<u32>> {
689        self.array_dimensions.clone()
690    }
691
692    pub fn set_array_dimensions(&mut self, array_dimensions: &[u32]) {
693        self.array_dimensions = Some(array_dimensions.to_vec());
694    }
695
696    pub fn data_type(&self) -> NodeId {
697        self.data_type.clone()
698    }
699
700    pub fn set_data_type<T>(&mut self, data_type: T)
701    where
702        T: Into<NodeId>,
703    {
704        self.data_type = data_type.into();
705    }
706}