Completed
Pull Request — master (#509)
by
unknown
04:19
created

Node.delete_reference()   B

Complexity

Conditions 5

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 25.3237

Importance

Changes 0
Metric Value
cc 5
dl 0
loc 22
ccs 1
cts 15
cp 0.0667
crap 25.3237
rs 8.3411
c 0
b 0
f 0
1
"""
2
High level node object, to access node attribute
3
and browse address space
4
"""
5
6 1
from opcua import ua
7 1
from opcua.common import events
8 1
import opcua.common
9
10 1
def _check_results(results, reqlen = 1):
11 1
    assert len(results) == reqlen, results
12 1
    for r in results:
13 1
        assert len(results) >= minlen, len(results)
14
        r.check()
15
16 1
def _to_nodeid(nodeid):
17 1
    if isinstance(nodeid, int):
18 1
        return ua.TwoByteNodeId(nodeid)
19 1
    elif isinstance(nodeid, Node):
20 1
        return nodeid.nodeid
21
    elif isinstance(nodeid, ua.NodeId):
22
        return nodeid
23
    elif type(nodeid) in (str, bytes):
24
        return ua.NodeId.from_string(nodeid)
25
    else:
26
        raise ua.UaError("Could not resolve '{0}' to a type id".format(nodeid))
27
28 1
class Node(object):
29
30
    """
31
    High level node object, to access node attribute,
32
    browse and populate address space.
33
    Node objects are usefull as-is but they do not expose the entire
34
    OPC-UA protocol. Feel free to look at the code of this class and call
35
    directly UA services methods to optimize your code
36
    """
37
38 1
    def __init__(self, server, nodeid):
39 1
        self.server = server
40 1
        self.nodeid = None
41 1
        if isinstance(nodeid, Node):
42 1
            self.nodeid = nodeid.nodeid
43 1
        elif isinstance(nodeid, ua.NodeId):
44 1
            self.nodeid = nodeid
45 1
        elif type(nodeid) in (str, bytes):
46 1
            self.nodeid = ua.NodeId.from_string(nodeid)
47 1
        elif isinstance(nodeid, int):
48 1
            self.nodeid = ua.NodeId(nodeid, 0)
49
        else:
50
            raise ua.UaError("argument to node must be a NodeId object or a string defining a nodeid found {0} of type {1}".format(nodeid, type(nodeid)))
51
52 1
    def __eq__(self, other):
53 1
        if isinstance(other, Node) and self.nodeid == other.nodeid:
54 1
            return True
55 1
        return False
56
57 1
    def __ne__(self, other):
58
        return not self.__eq__(other)
59
60 1
    def __str__(self):
61 1
        return "Node({0})".format(self.nodeid)
62 1
    __repr__ = __str__
63
64 1
    def __hash__(self):
65 1
        return self.nodeid.__hash__()
66
67 1
    def get_browse_name(self):
68
        """
69
        Get browse name of a node. A browse name is a QualifiedName object
70
        composed of a string(name) and a namespace index.
71
        """
72 1
        result = self.get_attribute(ua.AttributeIds.BrowseName)
73 1
        return result.Value.Value
74
75 1
    def get_display_name(self):
76
        """
77
        get description attribute of node
78
        """
79 1
        result = self.get_attribute(ua.AttributeIds.DisplayName)
80 1
        return result.Value.Value
81
82 1
    def get_data_type(self):
83
        """
84
        get data type of node as NodeId
85
        """
86 1
        result = self.get_attribute(ua.AttributeIds.DataType)
87 1
        return result.Value.Value
88
89 1
    def get_data_type_as_variant_type(self):
90
        """
91
        get data type of node as VariantType
92
        This only works if node is a variable, otherwise type
93
        may not be convertible to VariantType
94
        """
95 1
        result = self.get_attribute(ua.AttributeIds.DataType)
96 1
        return opcua.common.ua_utils.data_type_to_variant_type(Node(self.server, result.Value.Value))
97
98 1
    def get_access_level(self):
99
        """
100
        Get the access level attribute of the node as a set of AccessLevel enum values.
101
        """
102
        result = self.get_attribute(ua.AttributeIds.AccessLevel)
103
        return ua.AccessLevel.parse_bitfield(result.Value.Value)
104
105 1
    def get_user_access_level(self):
106
        """
107
        Get the user access level attribute of the node as a set of AccessLevel enum values.
108
        """
109
        result = self.get_attribute(ua.AttributeIds.UserAccessLevel)
110
        return ua.AccessLevel.parse_bitfield(result.Value.Value)
111
112 1
    def get_event_notifier(self):
113
        """
114
        Get the event notifier attribute of the node as a set of EventNotifier enum values.
115
        """
116 1
        result = self.get_attribute(ua.AttributeIds.EventNotifier)
117 1
        return ua.EventNotifier.parse_bitfield(result.Value.Value)
118
119 1
    def set_event_notifier(self, values):
120
        """
121
        Set the event notifier attribute.
122
123
        :param values: an iterable of EventNotifier enum values.
124
        """
125 1
        event_notifier_bitfield = ua.EventNotifier.to_bitfield(values)
126 1
        self.set_attribute(ua.AttributeIds.EventNotifier, ua.DataValue(ua.Variant(event_notifier_bitfield, ua.VariantType.Byte)))
127
128 1
    def get_node_class(self):
129
        """
130
        get node class attribute of node
131
        """
132 1
        result = self.get_attribute(ua.AttributeIds.NodeClass)
133 1
        return result.Value.Value
134
135 1
    def get_description(self):
136
        """
137
        get description attribute class of node
138
        """
139 1
        result = self.get_attribute(ua.AttributeIds.Description)
140 1
        return result.Value.Value
141
142 1
    def get_value(self):
143
        """
144
        Get value of a node as a python type. Only variables ( and properties) have values.
145
        An exception will be generated for other node types.
146
        """
147 1
        result = self.get_data_value()
148 1
        return result.Value.Value
149
150 1
    def get_data_value(self):
151
        """
152
        Get value of a node as a DataValue object. Only variables (and properties) have values.
153
        An exception will be generated for other node types.
154
        DataValue contain a variable value as a variant as well as server and source timestamps
155
        """
156 1
        return self.get_attribute(ua.AttributeIds.Value)
157
158 1
    def set_array_dimensions(self, value):
159
        """
160
        Set attribute ArrayDimensions of node
161
        make sure it has the correct data type
162
        """
163 1
        v = ua.Variant(value, ua.VariantType.UInt32)
164 1
        self.set_attribute(ua.AttributeIds.ArrayDimensions, ua.DataValue(v))
165
166 1
    def get_array_dimensions(self):
167
        """
168
        Read and return ArrayDimensions attribute of node
169
        """
170 1
        res = self.get_attribute(ua.AttributeIds.ArrayDimensions)
171 1
        return res.Value.Value
172
173 1
    def set_value_rank(self, value):
174
        """
175
        Set attribute ArrayDimensions of node
176
        """
177 1
        v = ua.Variant(value, ua.VariantType.Int32)
178 1
        self.set_attribute(ua.AttributeIds.ValueRank, ua.DataValue(v))
179
180 1
    def get_value_rank(self):
181
        """
182
        Read and return ArrayDimensions attribute of node
183
        """
184 1
        res = self.get_attribute(ua.AttributeIds.ValueRank)
185 1
        return res.Value.Value
186
187 1
    def set_value(self, value, varianttype=None):
188
        """
189
        Set value of a node. Only variables(properties) have values.
190
        An exception will be generated for other node types.
191
        value argument is either:
192
        * a python built-in type, converted to opc-ua
193
        optionnaly using the variantype argument.
194
        * a ua.Variant, varianttype is then ignored
195
        * a ua.DataValue, you then have full control over data send to server
196
        """
197 1
        datavalue = None
198 1
        if isinstance(value, ua.DataValue):
199 1
            datavalue = value
200 1
        elif isinstance(value, ua.Variant):
201 1
            datavalue = ua.DataValue(value)
202
        else:
203 1
            datavalue = ua.DataValue(ua.Variant(value, varianttype))
204 1
        self.set_attribute(ua.AttributeIds.Value, datavalue)
205
206 1
    set_data_value = set_value
207
208 1
    def set_writable(self, writable=True):
209
        """
210
        Set node as writable by clients.
211
        A node is always writable on server side.
212
        """
213 1
        if writable:
214 1
            self.set_attr_bit(ua.AttributeIds.AccessLevel, ua.AccessLevel.CurrentWrite)
215 1
            self.set_attr_bit(ua.AttributeIds.UserAccessLevel, ua.AccessLevel.CurrentWrite)
216
        else:
217 1
            self.unset_attr_bit(ua.AttributeIds.AccessLevel, ua.AccessLevel.CurrentWrite)
218 1
            self.unset_attr_bit(ua.AttributeIds.UserAccessLevel, ua.AccessLevel.CurrentWrite)
219
220 1
    def set_attr_bit(self, attr, bit):
221 1
        val = self.get_attribute(attr)
222 1
        val.Value.Value = ua.ua_binary.set_bit(val.Value.Value, bit)
223 1
        self.set_attribute(attr, val)
224
225 1
    def unset_attr_bit(self, attr, bit):
226 1
        val = self.get_attribute(attr)
227 1
        val.Value.Value = ua.ua_binary.unset_bit(val.Value.Value, bit)
228 1
        self.set_attribute(attr, val)
229
230 1
    def set_read_only(self):
231
        """
232
        Set a node as read-only for clients.
233
        A node is always writable on server side.
234
        """
235
        return self.set_writable(False)
236
237 1
    def set_attribute(self, attributeid, datavalue):
238
        """
239
        Set an attribute of a node
240
        attributeid is a member of ua.AttributeIds
241
        datavalue is a ua.DataValue object
242
        """
243 1
        attr = ua.WriteValue()
244 1
        attr.NodeId = self.nodeid
245 1
        attr.AttributeId = attributeid
246 1
        attr.Value = datavalue
247 1
        params = ua.WriteParameters()
248 1
        params.NodesToWrite = [attr]
249 1
        result = self.server.write(params)
250 1
        result[0].check()
251
252 1
    def get_attribute(self, attr):
253
        """
254
        Read one attribute of a node
255
        result code from server is checked and an exception is raised in case of error
256
        """
257 1
        rv = ua.ReadValueId()
258 1
        rv.NodeId = self.nodeid
259 1
        rv.AttributeId = attr
260 1
        params = ua.ReadParameters()
261 1
        params.NodesToRead.append(rv)
262 1
        result = self.server.read(params)
263 1
        result[0].StatusCode.check()
264 1
        return result[0]
265
266 1
    def get_attributes(self, attrs):
267
        """
268
        Read several attributes of a node
269
        list of DataValue is returned
270
        """
271 1
        params = ua.ReadParameters()
272 1
        for attr in attrs:
273 1
            rv = ua.ReadValueId()
274 1
            rv.NodeId = self.nodeid
275 1
            rv.AttributeId = attr
276 1
            params.NodesToRead.append(rv)
277
278 1
        results = self.server.read(params)
279 1
        return results
280
281 1
    def get_children(self, refs=ua.ObjectIds.HierarchicalReferences, nodeclassmask=ua.NodeClass.Unspecified):
282
        """
283
        Get all children of a node. By default hierarchical references and all node classes are returned.
284
        Other reference types may be given:
285
        References = 31
286
        NonHierarchicalReferences = 32
287
        HierarchicalReferences = 33
288
        HasChild = 34
289
        Organizes = 35
290
        HasEventSource = 36
291
        HasModellingRule = 37
292
        HasEncoding = 38
293
        HasDescription = 39
294
        HasTypeDefinition = 40
295
        GeneratesEvent = 41
296
        Aggregates = 44
297
        HasSubtype = 45
298
        HasProperty = 46
299
        HasComponent = 47
300
        HasNotifier = 48
301
        HasOrderedComponent = 49
302
        """
303 1
        return self.get_referenced_nodes(refs, ua.BrowseDirection.Forward, nodeclassmask)
304
305 1
    def get_properties(self):
306
        """
307
        return properties of node.
308
        properties are child nodes with a reference of type HasProperty and a NodeClass of Variable
309
        """
310 1
        return self.get_children(refs=ua.ObjectIds.HasProperty, nodeclassmask=ua.NodeClass.Variable)
311
312 1
    def get_variables(self):
313
        """
314
        return variables of node.
315
        properties are child nodes with a reference of type HasComponent and a NodeClass of Variable
316
        """
317 1
        return self.get_children(refs=ua.ObjectIds.HasComponent, nodeclassmask=ua.NodeClass.Variable)
318
319 1
    def get_methods(self):
320
        """
321
        return methods of node.
322
        properties are child nodes with a reference of type HasComponent and a NodeClass of Method
323
        """
324 1
        return self.get_children(refs=ua.ObjectIds.HasComponent, nodeclassmask=ua.NodeClass.Method)
325
326 1
    def get_children_descriptions(self, refs=ua.ObjectIds.HierarchicalReferences, nodeclassmask=ua.NodeClass.Unspecified, includesubtypes=True):
327 1
        return self.get_references(refs, ua.BrowseDirection.Forward, nodeclassmask, includesubtypes)
328
329 1
    def get_encoding_refs(self):
330
        return self.get_referenced_nodes(ua.ObjectIds.HasEncoding, ua.BrowseDirection.Forward)
331
332 1
    def get_description_refs(self):
333
        return self.get_referenced_nodes(ua.ObjectIds.HasDescription, ua.BrowseDirection.Forward)
334
335 1
    def get_references(self, refs=ua.ObjectIds.References, direction=ua.BrowseDirection.Both, nodeclassmask=ua.NodeClass.Unspecified, includesubtypes=True):
336
        """
337
        returns references of the node based on specific filter defined with:
338
339
        refs = ObjectId of the Reference
340
        direction = Browse direction for references
341
        nodeclassmask = filter nodes based on specific class
342
        includesubtypes = If true subtypes of the reference (ref) are also included
343
        """
344 1
        desc = ua.BrowseDescription()
345 1
        desc.BrowseDirection = direction
346 1
        desc.ReferenceTypeId = _to_nodeid(refs)
347 1
        desc.IncludeSubtypes = includesubtypes
348 1
        desc.NodeClassMask = nodeclassmask
349 1
        desc.ResultMask = ua.BrowseResultMask.All
350
351 1
        desc.NodeId = self.nodeid
352 1
        params = ua.BrowseParameters()
353 1
        params.View.Timestamp = ua.get_win_epoch()
354 1
        params.NodesToBrowse.append(desc)
355 1
        params.RequestedMaxReferencesPerNode = 0
356 1
        results = self.server.browse(params)
357
358 1
        references = self._browse_next(results)
359 1
        return references
360
361 1
    def _browse_next(self, results):
362 1
        references = results[0].References
363 1
        while results[0].ContinuationPoint:
364
            params = ua.BrowseNextParameters()
365
            params.ContinuationPoints = [results[0].ContinuationPoint]
366
            params.ReleaseContinuationPoints = False
367
            results = self.server.browse_next(params)
368
            references.extend(results[0].References)
369 1
        return references
370
371 1
    def get_referenced_nodes(self, refs=ua.ObjectIds.References, direction=ua.BrowseDirection.Both, nodeclassmask=ua.NodeClass.Unspecified, includesubtypes=True):
372
        """
373
        returns referenced nodes based on specific filter
374
        Paramters are the same as for get_references
375
376
        """
377 1
        references = self.get_references(refs, direction, nodeclassmask, includesubtypes)
378 1
        nodes = []
379 1
        for desc in references:
380 1
            node = Node(self.server, desc.NodeId)
381 1
            nodes.append(node)
382 1
        return nodes
383
384 1
    def get_type_definition(self):
385
        """
386
        returns type definition of the node.
387
        """
388 1
        references = self.get_references(refs=ua.ObjectIds.HasTypeDefinition, direction=ua.BrowseDirection.Forward)
389 1
        if len(references) == 0:
390 1
            return None
391 1
        return references[0].NodeId
392
393 1
    def get_path(self, max_length=20, as_string=False):
394
        """
395
        Attempt to find path of node from root node and return it as a list of Nodes.
396
        There might several possible paths to a node, this function will return one
397
        Some nodes may be missing references, so this method may
398
        return an empty list
399
        Since address space may have circular references, a max length is specified
400
401
        """
402 1
        path = self._get_path(max_length)
403 1
        path = [Node(self.server, ref.NodeId) for ref in path]
404 1
        path.append(self)
405 1
        if as_string:
406 1
            path = [el.get_browse_name().to_string() for el in path]
407 1
        return path
408
409 1
    def _get_path(self, max_length=20):
410
        """
411
        Attempt to find path of node from root node and return it as a list of Nodes.
412
        There might several possible paths to a node, this function will return one
413
        Some nodes may be missing references, so this method may
414
        return an empty list
415
        Since address space may have circular references, a max length is specified
416
417
        """
418 1
        path = []
419 1
        node = self
420 1
        while True:
421 1
            refs = node.get_references(refs=ua.ObjectIds.HierarchicalReferences, direction=ua.BrowseDirection.Inverse)
422 1
            if len(refs) > 0:
423 1
                path.insert(0, refs[0])
424 1
                node = Node(self.server, refs[0].NodeId)
425 1
                if len(path) >= (max_length -1):
426 1
                    return path
427
            else:
428 1
                return path
429
430 1
    def get_parent(self):
431
        """
432
        returns parent of the node.
433
        A Node may have several parents, the first found is returned.
434
        This method uses reverse references, a node might be missing such a link,
435
        thus we will not find its parent.
436
        """
437 1
        refs = self.get_references(refs=ua.ObjectIds.HierarchicalReferences, direction=ua.BrowseDirection.Inverse)
438 1
        if len(refs) > 0:
439 1
            return Node(self.server, refs[0].NodeId)
440
        else:
441
            return None
442
443 1
    def get_child(self, path):
444
        """
445
        get a child specified by its path from this node.
446
        A path might be:
447
        * a string representing a qualified name.
448
        * a qualified name
449
        * a list of string
450
        * a list of qualified names
451
        """
452 1
        if type(path) not in (list, tuple):
453 1
            path = [path]
454 1
        rpath = self._make_relative_path(path)
455 1
        bpath = ua.BrowsePath()
456 1
        bpath.StartingNode = self.nodeid
457 1
        bpath.RelativePath = rpath
458 1
        result = self.server.translate_browsepaths_to_nodeids([bpath])
459 1
        result = result[0]
460 1
        result.StatusCode.check()
461
        # FIXME: seems this method may return several nodes
462 1
        return Node(self.server, result.Targets[0].TargetId)
463
464 1
    def _make_relative_path(self, path):
465 1
        rpath = ua.RelativePath()
466 1
        for item in path:
467 1
            el = ua.RelativePathElement()
468 1
            el.ReferenceTypeId = ua.TwoByteNodeId(ua.ObjectIds.HierarchicalReferences)
469 1
            el.IsInverse = False
470 1
            el.IncludeSubtypes = True
471 1
            if isinstance(item, ua.QualifiedName):
472
                el.TargetName = item
473
            else:
474 1
                el.TargetName = ua.QualifiedName.from_string(item)
475 1
            rpath.Elements.append(el)
476 1
        return rpath
477
478 1
    def read_raw_history(self, starttime=None, endtime=None, numvalues=0):
479
        """
480
        Read raw history of a node
481
        result code from server is checked and an exception is raised in case of error
482
        If numvalues is > 0 and number of events in period is > numvalues
483
        then result will be truncated
484
        """
485 1
        details = ua.ReadRawModifiedDetails()
486 1
        details.IsReadModified = False
487 1
        if starttime:
488 1
            details.StartTime = starttime
489
        else:
490 1
            details.StartTime = ua.get_win_epoch()
491 1
        if endtime:
492 1
            details.EndTime = endtime
493
        else:
494 1
            details.EndTime = ua.get_win_epoch()
495 1
        details.NumValuesPerNode = numvalues
496 1
        details.ReturnBounds = True
497 1
        result = self.history_read(details)
498 1
        return result.HistoryData.DataValues
499
500 1
    def history_read(self, details):
501
        """
502
        Read raw history of a node, low-level function
503
        result code from server is checked and an exception is raised in case of error
504
        """
505 1
        valueid = ua.HistoryReadValueId()
506 1
        valueid.NodeId = self.nodeid
507 1
        valueid.IndexRange = ''
508
509 1
        params = ua.HistoryReadParameters()
510 1
        params.HistoryReadDetails = details
511 1
        params.TimestampsToReturn = ua.TimestampsToReturn.Both
512 1
        params.ReleaseContinuationPoints = False
513 1
        params.NodesToRead.append(valueid)
514 1
        result = self.server.history_read(params)[0]
515 1
        return result
516
517 1
    def read_event_history(self, starttime=None, endtime=None, numvalues=0, evtypes=ua.ObjectIds.BaseEventType):
518
        """
519
        Read event history of a source node
520
        result code from server is checked and an exception is raised in case of error
521
        If numvalues is > 0 and number of events in period is > numvalues
522
        then result will be truncated
523
        """
524
525 1
        details = ua.ReadEventDetails()
526 1
        if starttime:
527 1
            details.StartTime = starttime
528
        else:
529 1
            details.StartTime = ua.get_win_epoch()
530 1
        if endtime:
531 1
            details.EndTime = endtime
532
        else:
533 1
            details.EndTime = ua.get_win_epoch()
534 1
        details.NumValuesPerNode = numvalues
535
536 1
        if not isinstance(evtypes, (list, tuple)):
537 1
            evtypes = [evtypes]
538
539 1
        evtypes = [Node(self.server, evtype) for evtype in evtypes]
540
541 1
        evfilter = events.get_filter_from_event_type(evtypes)
542 1
        details.Filter = evfilter
543
544 1
        result = self.history_read_events(details)
545 1
        event_res = []
546 1
        for res in result.HistoryData.Events:
547 1
            event_res.append(events.Event.from_event_fields(evfilter.SelectClauses, res.EventFields))
548 1
        return event_res
549
550 1
    def history_read_events(self, details):
551
        """
552
        Read event history of a node, low-level function
553
        result code from server is checked and an exception is raised in case of error
554
        """
555 1
        valueid = ua.HistoryReadValueId()
556 1
        valueid.NodeId = self.nodeid
557 1
        valueid.IndexRange = ''
558
559 1
        params = ua.HistoryReadParameters()
560 1
        params.HistoryReadDetails = details
561 1
        params.TimestampsToReturn = ua.TimestampsToReturn.Both
562 1
        params.ReleaseContinuationPoints = False
563 1
        params.NodesToRead.append(valueid)
564 1
        result = self.server.history_read(params)[0]
565 1
        return result
566
567 1
    def delete(self, delete_references=True, recursive=False):
568
        """
569
        Delete node from address space
570
        """
571
        results = opcua.common.manage_nodes.delete_nodes(self.server, [self], recursive, delete_references)
572
        _check_results(results)
573
574 1
    def delete_reference(self, target, reftype, forward=True, bidirectional=True):
575
        """
576
        Delete given node's references from address space
577
        """
578
        known_refs = self.get_references(reftype, includesubtypes=False)
579
        targetid = _to_nodeid(target)
580
581
        for r in known_refs:
582
            if r.NodeId == targetid and r.IsForward == forward:
583
                rdesc = r
584
                break
585
        else:
586
            raise ua.UaStatusCodeError(ua.StatusCodes.BadNotFound)
587
588
        ditem = ua.DeleteReferencesItem()
589
        ditem.SourceNodeId = self.nodeid
590
        ditem.TargetNodeId = rdesc.NodeId
591
        ditem.ReferenceTypeId = rdesc.ReferenceTypeId
592
        ditem.IsForward = rdesc.IsForward
593
        ditem.DeleteBidirectional = bidirectional
594
595
        self.server.delete_references([ditem])[0].check()
596
597 1
    def add_reference(self, target, reftype, forward=True, bidirectional=True):
598
        """
599
        Add reference to node
600
        """
601
602 1
        aitem = ua.AddReferencesItem()
603 1
        aitem.SourceNodeId = self.nodeid
604 1
        aitem.TargetNodeId = _to_nodeid(target)
605 1
        aitem.ReferenceTypeId = _to_nodeid(reftype)
606 1
        aitem.IsForward = forward
607
608 1
        params = [aitem]
609
610 1
        if bidirectional:
611 1
            aitem2 = ua.AddReferencesItem()
612 1
            aitem2.SourceNodeId = aitem.TargetNodeId
613 1
            aitem2.TargetNodeId = aitem.SourceNodeId
614 1
            aitem2.ReferenceTypeId = aitem.ReferenceTypeId
615 1
            aitem2.IsForward = not forward
616 1
            params.append(aitem2)
617
618 1
        results =  self.server.add_references(params)
619 1
        _check_results(results, len(params))
620
621 1
    def add_folder(self, nodeid, bname):
622 1
        return  opcua.common.manage_nodes.create_folder(self, nodeid, bname)
623
624 1
    def add_object(self, nodeid, bname, objecttype=None):
625 1
        return opcua.common.manage_nodes.create_object(self, nodeid, bname, objecttype)
626
627 1
    def add_variable(self, nodeid, bname, val, varianttype=None, datatype=None):
628 1
        return opcua.common.manage_nodes.create_variable(self, nodeid, bname, val, varianttype, datatype)
629
630 1
    def add_object_type(self, nodeid, bname):
631 1
        return opcua.common.manage_nodes.create_object_type(self, nodeid, bname)
632
633 1
    def add_variable_type(self, nodeid, bname, datatype):
634
        return opcua.common.manage_nodes.create_variable_type(self, nodeid, bname, datatype)
635
636 1
    def add_data_type(self, nodeid, bname, description=None):
637 1
        return opcua.common.manage_nodes.create_data_type(self, nodeid, bname, description=None)
638
639 1
    def add_property(self, nodeid, bname, val, varianttype=None, datatype=None):
640 1
        return opcua.common.manage_nodes.create_property(self, nodeid, bname, val, varianttype, datatype)
641
642 1
    def add_method(self, *args):
643 1
        return opcua.common.manage_nodes.create_method(self, *args)
644
645 1
    def add_reference_type(self, nodeid, bname, symmetric=True, inversename=None):
646 1
        return opcua.common.manage_nodes.create_reference_type(self, nodeid, bname, symmetric, inversename)
647
648 1
    def call_method(self, methodid, *args):
649
        return opcua.common.methods.call_method(self, methodid, *args)
650