1
|
1 |
|
from opcua import ua |
2
|
1 |
|
from opcua.common.node import Node |
3
|
|
|
|
4
|
|
|
|
5
|
1 |
|
def copy_node(parent, node, nodeid=None, recursive=True): |
6
|
|
|
""" |
7
|
|
|
Copy a node or node tree as child of parent node |
8
|
|
|
""" |
9
|
1 |
|
print("Copying", node, "into ", parent) |
10
|
1 |
|
rdesc = _rdesc_from_node(parent, node) |
11
|
|
|
|
12
|
1 |
|
if nodeid is None: |
13
|
1 |
|
nodeid = ua.NodeId(namespaceidx=node.nodeid.NamespaceIndex) |
14
|
1 |
|
added_nodeids = _copy_node(parent.server, parent.nodeid, rdesc, nodeid, recursive) |
15
|
1 |
|
return [Node(parent.server, nid) for nid in added_nodeids] |
16
|
|
|
|
17
|
|
|
|
18
|
1 |
|
def _copy_node(server, parent_nodeid, rdesc, nodeid, recursive): |
19
|
1 |
|
addnode = ua.AddNodesItem() |
20
|
1 |
|
addnode.RequestedNewNodeId = nodeid |
21
|
1 |
|
addnode.BrowseName = rdesc.BrowseName |
22
|
1 |
|
addnode.ParentNodeId = parent_nodeid |
23
|
1 |
|
addnode.ReferenceTypeId = rdesc.ReferenceTypeId |
24
|
1 |
|
addnode.TypeDefinition = rdesc.TypeDefinition |
25
|
1 |
|
addnode.NodeClass = rdesc.NodeClass |
26
|
|
|
|
27
|
1 |
|
node_to_copy = Node(server, rdesc.NodeId) |
28
|
|
|
|
29
|
1 |
|
attrObj = getattr(ua, rdesc.NodeClass.name + "Attributes") |
30
|
1 |
|
_read_and_copy_attrs(node_to_copy, attrObj(), addnode) |
31
|
|
|
|
32
|
1 |
|
res = server.add_nodes([addnode])[0] |
33
|
|
|
|
34
|
1 |
|
added_nodes = [res.AddedNodeId] |
35
|
|
|
|
36
|
1 |
|
if recursive: |
37
|
1 |
|
descs = node_to_copy.get_children_descriptions() |
38
|
1 |
|
for desc in descs: |
39
|
1 |
|
nodes = _copy_node(server, res.AddedNodeId, desc, nodeid=ua.NodeId(namespaceidx=desc.NodeId.NamespaceIndex), recursive=True) |
40
|
1 |
|
added_nodes.extend(nodes) |
41
|
|
|
|
42
|
1 |
|
return added_nodes |
43
|
|
|
|
44
|
|
|
|
45
|
1 |
|
def _rdesc_from_node(parent, node): |
46
|
1 |
|
results = node.get_attributes([ua.AttributeIds.NodeClass, ua.AttributeIds.BrowseName, ua.AttributeIds.DisplayName]) |
47
|
1 |
|
nclass, qname, dname = [res.Value.Value for res in results] |
48
|
|
|
|
49
|
1 |
|
rdesc = ua.ReferenceDescription() |
50
|
1 |
|
rdesc.NodeId = node.nodeid |
51
|
1 |
|
rdesc.BrowseName = qname |
52
|
1 |
|
rdesc.DisplayName = dname |
53
|
1 |
|
rdesc.NodeClass = nclass |
54
|
1 |
|
if parent.get_type_definition() == ua.NodeId(ua.ObjectIds.FolderType): |
55
|
1 |
|
rdesc.ReferenceTypeId = ua.NodeId(ua.ObjectIds.Organizes) |
56
|
|
|
else: |
57
|
|
|
rdesc.ReferenceTypeId = ua.NodeId(ua.ObjectIds.HasComponent) |
58
|
1 |
|
typedef = node.get_type_definition() |
59
|
1 |
|
if typedef: |
60
|
|
|
rdesc.TypeDefinition = typedef |
61
|
1 |
|
return rdesc |
62
|
|
|
|
63
|
|
|
|
64
|
1 |
|
def _read_and_copy_attrs(node_type, struct, addnode): |
65
|
1 |
|
names = [name for name in struct.__dict__.keys() if not name.startswith("_") and name not in ("BodyLength", "TypeId", "SpecifiedAttributes", "Encoding", "IsAbstract", "EventNotifier")] |
66
|
1 |
|
attrs = [getattr(ua.AttributeIds, name) for name in names] |
67
|
1 |
|
for name in names: |
68
|
1 |
|
results = node_type.get_attributes(attrs) |
69
|
1 |
|
for idx, name in enumerate(names): |
70
|
1 |
|
if results[idx].StatusCode.is_good(): |
71
|
1 |
|
if name == "Value": |
72
|
1 |
|
setattr(struct, name, results[idx].Value) |
73
|
|
|
else: |
74
|
1 |
|
setattr(struct, name, results[idx].Value.Value) |
75
|
|
|
else: |
76
|
|
|
print("Instantiate: while copying attributes from node type %s, attribute %s, statuscode is %s" % (node_type, name, results[idx].StatusCode)) |
77
|
|
|
addnode.NodeAttributes = struct |
78
|
|
|
|