opcua/server/address_space/
object.rs1use crate::types::service_types::ObjectAttributes;
8
9use super::{base::Base, node::Node, node::NodeBase, EventNotifier};
10
11node_builder_impl!(ObjectBuilder, Object);
12node_builder_impl_component_of!(ObjectBuilder);
13node_builder_impl_property_of!(ObjectBuilder);
14
15impl ObjectBuilder {
16 pub fn is_folder(self) -> Self {
17 self.has_type_definition(ObjectTypeId::FolderType)
18 }
19
20 pub fn event_notifier(mut self, event_notifier: EventNotifier) -> Self {
21 self.node.set_event_notifier(event_notifier);
22 self
23 }
24
25 pub fn has_type_definition<T>(self, type_id: T) -> Self
26 where
27 T: Into<NodeId>,
28 {
29 self.reference(
30 type_id,
31 ReferenceTypeId::HasTypeDefinition,
32 ReferenceDirection::Forward,
33 )
34 }
35
36 pub fn has_event_source<T>(self, source_id: T) -> Self
37 where
38 T: Into<NodeId>,
39 {
40 self.reference(
41 source_id,
42 ReferenceTypeId::HasEventSource,
43 ReferenceDirection::Forward,
44 )
45 }
46}
47
48#[derive(Debug)]
50pub struct Object {
51 base: Base,
52 event_notifier: EventNotifier,
53}
54
55impl Default for Object {
56 fn default() -> Self {
57 Self {
58 base: Base::new(NodeClass::Object, &NodeId::null(), "", ""),
59 event_notifier: EventNotifier::empty(),
60 }
61 }
62}
63
64node_base_impl!(Object);
65
66impl Node for Object {
67 fn get_attribute_max_age(
68 &self,
69 timestamps_to_return: TimestampsToReturn,
70 attribute_id: AttributeId,
71 index_range: NumericRange,
72 data_encoding: &QualifiedName,
73 max_age: f64,
74 ) -> Option<DataValue> {
75 match attribute_id {
76 AttributeId::EventNotifier => Some(self.event_notifier().bits().into()),
77 _ => self.base.get_attribute_max_age(
78 timestamps_to_return,
79 attribute_id,
80 index_range,
81 data_encoding,
82 max_age,
83 ),
84 }
85 }
86
87 fn set_attribute(
88 &mut self,
89 attribute_id: AttributeId,
90 value: Variant,
91 ) -> Result<(), StatusCode> {
92 match attribute_id {
93 AttributeId::EventNotifier => {
94 if let Variant::Byte(v) = value {
95 self.set_event_notifier(EventNotifier::from_bits_truncate(v));
96 Ok(())
97 } else {
98 Err(StatusCode::BadTypeMismatch)
99 }
100 }
101 _ => self.base.set_attribute(attribute_id, value),
102 }
103 }
104}
105
106impl Object {
107 pub fn new<R, S>(
108 node_id: &NodeId,
109 browse_name: R,
110 display_name: S,
111 event_notifier: EventNotifier,
112 ) -> Object
113 where
114 R: Into<QualifiedName>,
115 S: Into<LocalizedText>,
116 {
117 Object {
118 base: Base::new(NodeClass::Object, node_id, browse_name, display_name),
119 event_notifier,
120 }
121 }
122
123 pub fn from_attributes<S>(
124 node_id: &NodeId,
125 browse_name: S,
126 attributes: ObjectAttributes,
127 ) -> Result<Self, ()>
128 where
129 S: Into<QualifiedName>,
130 {
131 let mandatory_attributes = AttributesMask::DISPLAY_NAME | AttributesMask::EVENT_NOTIFIER;
132
133 let mask = AttributesMask::from_bits(attributes.specified_attributes).ok_or(())?;
134 if mask.contains(mandatory_attributes) {
135 let event_notifier = EventNotifier::from_bits_truncate(attributes.event_notifier);
136 let mut node = Self::new(
137 node_id,
138 browse_name,
139 attributes.display_name,
140 event_notifier,
141 );
142 if mask.contains(AttributesMask::DESCRIPTION) {
143 node.set_description(attributes.description);
144 }
145 if mask.contains(AttributesMask::WRITE_MASK) {
146 node.set_write_mask(WriteMask::from_bits_truncate(attributes.write_mask));
147 }
148 if mask.contains(AttributesMask::USER_WRITE_MASK) {
149 node.set_user_write_mask(WriteMask::from_bits_truncate(attributes.user_write_mask));
150 }
151 Ok(node)
152 } else {
153 error!("Object cannot be created from attributes - missing mandatory values");
154 Err(())
155 }
156 }
157
158 pub fn is_valid(&self) -> bool {
159 self.base.is_valid()
160 }
161
162 pub fn event_notifier(&self) -> EventNotifier {
163 self.event_notifier
164 }
165
166 pub fn set_event_notifier(&mut self, event_notifier: EventNotifier) {
167 self.event_notifier = event_notifier;
168 }
169}