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