Skip to main content

opcua_nodes/
node.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2024 Adam Lock
4
5use opcua_types::{
6    status_code::StatusCode, AttributeId, DataEncoding, DataValue, LocalizedText, NodeClass,
7    NodeId, NumericRange, QualifiedName, TimestampsToReturn, Variant, WriteMask,
8};
9
10use super::{DataType, Method, Object, ObjectType, ReferenceType, Variable, VariableType, View};
11
12/// The `NodeType` enum enumerates the different OPC-UA node classes.
13#[derive(Debug)]
14pub enum NodeType {
15    /// Objects are general structural nodes without special meaning.
16    Object(Box<Object>),
17    /// Object types define properties of object nodes.
18    ObjectType(Box<ObjectType>),
19    /// Reference types define properties of references.
20    ReferenceType(Box<ReferenceType>),
21    /// Variables are nodes with a current value that can be stored historically.
22    Variable(Box<Variable>),
23    /// Variable types define properties of variable nodes.
24    VariableType(Box<VariableType>),
25    /// Views are pre-defined subsets of the address space.
26    View(Box<View>),
27    /// Data types define different types used by variables.
28    DataType(Box<DataType>),
29    /// Methods are nodes that can be called with the `Call` service.
30    Method(Box<Method>),
31}
32
33/// Trait for types that have a node ID.
34pub trait HasNodeId {
35    /// Get the node ID of this item.
36    fn node_id(&self) -> &NodeId;
37}
38
39impl HasNodeId for NodeType {
40    fn node_id(&self) -> &NodeId {
41        self.as_node().node_id()
42    }
43}
44
45impl NodeType {
46    /// Get a reference to this as dyn [Node].
47    pub fn as_node<'a>(&'a self) -> &'a (dyn Node + 'a) {
48        match self {
49            NodeType::Object(value) => value.as_ref(),
50            NodeType::ObjectType(value) => value.as_ref(),
51            NodeType::ReferenceType(value) => value.as_ref(),
52            NodeType::Variable(value) => value.as_ref(),
53            NodeType::VariableType(value) => value.as_ref(),
54            NodeType::View(value) => value.as_ref(),
55            NodeType::DataType(value) => value.as_ref(),
56            NodeType::Method(value) => value.as_ref(),
57        }
58    }
59
60    /// Get a reference to this as mut dyn [Node].
61    pub fn as_mut_node(&mut self) -> &mut dyn Node {
62        match self {
63            NodeType::Object(ref mut value) => value.as_mut(),
64            NodeType::ObjectType(ref mut value) => value.as_mut(),
65            NodeType::ReferenceType(ref mut value) => value.as_mut(),
66            NodeType::Variable(ref mut value) => value.as_mut(),
67            NodeType::VariableType(ref mut value) => value.as_mut(),
68            NodeType::View(ref mut value) => value.as_mut(),
69            NodeType::DataType(ref mut value) => value.as_mut(),
70            NodeType::Method(ref mut value) => value.as_mut(),
71        }
72    }
73
74    /// Returns the [`NodeClass`] of this `NodeType`.
75    pub fn node_class(&self) -> NodeClass {
76        match self {
77            NodeType::Object(_) => NodeClass::Object,
78            NodeType::ObjectType(_) => NodeClass::ObjectType,
79            NodeType::ReferenceType(_) => NodeClass::ReferenceType,
80            NodeType::Variable(_) => NodeClass::Variable,
81            NodeType::VariableType(_) => NodeClass::VariableType,
82            NodeType::View(_) => NodeClass::View,
83            NodeType::DataType(_) => NodeClass::DataType,
84            NodeType::Method(_) => NodeClass::Method,
85        }
86    }
87}
88
89/// Implemented within a macro for all Node types. Functions that return a result in an Option
90/// do so because the attribute is optional and not necessarily there.
91pub trait NodeBase {
92    /// Returns the node class - Object, ObjectType, Method, DataType, ReferenceType, Variable, VariableType or View
93    fn node_class(&self) -> NodeClass;
94
95    /// Returns the node's `NodeId`
96    fn node_id(&self) -> &NodeId;
97
98    /// Returns the node's browse name
99    fn browse_name(&self) -> &QualifiedName;
100
101    /// Returns the node's display name
102    fn display_name(&self) -> &LocalizedText;
103
104    /// Sets the node's display name
105    fn set_display_name(&mut self, display_name: LocalizedText);
106
107    /// Get the description of this node.
108    fn description(&self) -> Option<&LocalizedText>;
109
110    /// Set the description of this node.
111    fn set_description(&mut self, description: LocalizedText);
112
113    /// Get the write mask of this node.
114    fn write_mask(&self) -> Option<WriteMask>;
115
116    /// Set the write mask of this node.
117    fn set_write_mask(&mut self, write_mask: WriteMask);
118
119    /// Get the user write mask for this node.
120    fn user_write_mask(&self) -> Option<WriteMask>;
121
122    /// Set the user write mask for this node.
123    fn set_user_write_mask(&mut self, write_mask: WriteMask);
124}
125
126/// Implemented by each node type's to provide a generic way to set or get attributes, e.g.
127/// from the Attributes service set. Internal callers could call the setter / getter on the node
128/// if they have access to them.
129pub trait Node: NodeBase {
130    /// Finds the attribute and value. The param `max_age` is a hint in milliseconds:
131    ///
132    /// * value 0, server shall attempt to read a new value from the data source
133    /// * value >= i32::max(), sever shall attempt to get a cached value
134    ///
135    /// If there is a getter registered with the node, then the getter will interpret
136    /// `max_age` how it sees fit.
137    fn get_attribute_max_age(
138        &self,
139        timestamps_to_return: TimestampsToReturn,
140        attribute_id: AttributeId,
141        index_range: &NumericRange,
142        data_encoding: &DataEncoding,
143        max_age: f64,
144    ) -> Option<DataValue>;
145
146    /// Finds the attribute and value.
147    fn get_attribute(
148        &self,
149        timestamps_to_return: TimestampsToReturn,
150        attribute_id: AttributeId,
151        index_range: &NumericRange,
152        data_encoding: &DataEncoding,
153    ) -> Option<DataValue> {
154        self.get_attribute_max_age(
155            timestamps_to_return,
156            attribute_id,
157            index_range,
158            data_encoding,
159            0f64,
160        )
161    }
162
163    /// Sets the attribute with the new value
164    fn set_attribute(
165        &mut self,
166        attribute_id: AttributeId,
167        value: Variant,
168    ) -> Result<(), StatusCode>;
169}