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