|
1
|
|
|
import xml.etree.ElementTree as ET |
|
2
|
|
|
import collections |
|
3
|
|
|
|
|
4
|
|
|
|
|
5
|
|
|
class Node_struct: |
|
6
|
|
|
|
|
7
|
|
|
def __init__(self): |
|
8
|
|
|
self.nodeId = None |
|
9
|
|
|
self.browseName = None |
|
10
|
|
|
self.isAbstract = True |
|
11
|
|
|
self.parentNodeId = None |
|
12
|
|
|
self.dataType = None |
|
13
|
|
|
self.displayName = None |
|
14
|
|
|
self.description = None |
|
15
|
|
|
self.references = [] |
|
16
|
|
|
|
|
17
|
|
|
def __hash__(self): |
|
18
|
|
|
return hash(self.nodeId, self.browseName, self.isAbstract, self.parentNodeId, self.dataType, self.displayName, |
|
19
|
|
|
self.description, self.references) |
|
20
|
|
|
|
|
21
|
|
|
def __eq__(self, other): |
|
22
|
|
|
return (self.nodeId, self.browseName, self.isAbstract, self.parentNodeId, self.dataType, self.displayName, |
|
23
|
|
|
self.description, self.references) == ( |
|
24
|
|
|
other.nodeId, other.browseName, other.isAbstract, other.parentNodeId, other.dataType, other.displayName, |
|
25
|
|
|
other.description, other.references) |
|
26
|
|
|
|
|
27
|
|
|
def __ne__(self, other): |
|
28
|
|
|
return not (self == other) |
|
29
|
|
|
|
|
30
|
|
|
|
|
31
|
|
|
class Reference: |
|
32
|
|
|
def __init__(self): |
|
33
|
|
|
self.referenceType = None |
|
34
|
|
|
self.refId = None |
|
35
|
|
|
|
|
36
|
|
|
def __hash__(self): |
|
37
|
|
|
return hash(self.referenceType, self.refId) |
|
38
|
|
|
|
|
39
|
|
|
def __eq__(self, other): |
|
40
|
|
|
return (self.referenceType, self.refId) == (other.referenceType, other.refValue) |
|
41
|
|
|
|
|
42
|
|
|
def __ne__(self, other): |
|
43
|
|
|
return not (self == other) |
|
44
|
|
|
|
|
45
|
|
|
|
|
46
|
|
|
class Model_Event: |
|
47
|
|
|
def __init__(self): |
|
48
|
|
|
self.structs = [] |
|
49
|
|
|
|
|
50
|
|
|
def get_struct(self, nodeId): |
|
51
|
|
|
for struct in self.structs: |
|
52
|
|
|
if struct.nodeId == nodeId: |
|
53
|
|
|
return struct |
|
54
|
|
|
raise Exception("No struct with the Id: " + str(nodeId)) |
|
55
|
|
|
|
|
56
|
|
|
|
|
57
|
|
|
class Parser(object): |
|
58
|
|
|
nameSpace = "{http://opcfoundation.org/UA/2011/03/UANodeSet.xsd}" |
|
59
|
|
|
|
|
60
|
|
|
def __init__(self, path): |
|
61
|
|
|
self.path = path |
|
62
|
|
|
self.model = None |
|
63
|
|
|
|
|
64
|
|
|
def findNodeWithNodeId(self, root, nodeId): |
|
65
|
|
|
node = Node_struct() |
|
66
|
|
|
for child in root: |
|
67
|
|
|
if nodeId == child.attrib.get('NodeId'): |
|
68
|
|
|
node.browseName = str(child.attrib.get('BrowseName')) |
|
69
|
|
|
node.nodeId = child.attrib.get('NodeId') |
|
70
|
|
|
node.isAbstract = child.attrib.get('IsAbstract') |
|
71
|
|
|
node.dataType = child.attrib.get('DataType') |
|
72
|
|
|
if node.dataType is None: |
|
73
|
|
|
node.dataType = 'Variant' |
|
74
|
|
|
node.displayName = child.find(self.nameSpace + 'DisplayName').text |
|
75
|
|
|
if child.find(self.nameSpace + 'Description') is not None: |
|
76
|
|
|
node.description = child.find(self.nameSpace + 'Description').text |
|
77
|
|
|
for ref in child.find(self.nameSpace + 'References').findall(self.nameSpace + 'Reference'): |
|
78
|
|
|
reference = Reference() |
|
79
|
|
|
reference.referenceType = ref.attrib.get('ReferenceType') |
|
80
|
|
|
reference.refId = ref.text |
|
81
|
|
|
if ref.attrib.get('IsForward') != None: |
|
82
|
|
|
node.parentNodeId = reference.refId |
|
83
|
|
|
node.references.append(reference) |
|
84
|
|
|
return node |
|
85
|
|
|
|
|
86
|
|
|
def checkNodeType(self, node): |
|
87
|
|
|
if ( |
|
88
|
|
|
(node.tag == self.nameSpace + "UAObjectType") or |
|
89
|
|
|
(node.tag == self.nameSpace + "UAVariable") or |
|
90
|
|
|
(node.tag == self.nameSpace + "UAObject") or |
|
91
|
|
|
(node.tag == self.nameSpace + "UAMethod") or |
|
92
|
|
|
(node.tag == self.nameSpace + "UAVariableType")): |
|
93
|
|
|
return True |
|
94
|
|
|
|
|
95
|
|
|
def parse(self): |
|
96
|
|
|
print("Parsing: " + self.path) |
|
97
|
|
|
tree = ET.parse(self.path) |
|
98
|
|
|
root = tree.getroot() |
|
99
|
|
|
listEventType = {} |
|
100
|
|
|
for child in root: |
|
101
|
|
|
browseName = str(child.attrib.get('BrowseName')) |
|
102
|
|
|
if browseName.endswith("EventType"): |
|
103
|
|
|
if browseName == "EventType": |
|
104
|
|
|
continue |
|
105
|
|
|
node = Node_struct() |
|
106
|
|
|
node.browseName = browseName.replace("Type", "") |
|
107
|
|
|
node.nodeId = child.attrib.get('NodeId') |
|
108
|
|
|
node.isAbstract = child.attrib.get('IsAbstract') |
|
109
|
|
|
node.displayName = child.find(self.nameSpace + 'DisplayName').text |
|
110
|
|
|
if child.find(self.nameSpace + 'Description') is not None: |
|
111
|
|
|
node.description = child.find(self.nameSpace + 'Description').text |
|
112
|
|
|
for ref in child.find(self.nameSpace + 'References').findall(self.nameSpace + 'Reference'): |
|
113
|
|
|
reference = Reference() |
|
114
|
|
|
reference.referenceType = ref.attrib.get('ReferenceType') |
|
115
|
|
|
reference.refId = ref.text |
|
116
|
|
|
self.refNode = self.findNodeWithNodeId(root, reference.refId).browseName |
|
117
|
|
|
reference.refBrowseName = self.findNodeWithNodeId(root, reference.refId).browseName |
|
118
|
|
|
reference.refDataType = self.findNodeWithNodeId(root, reference.refId).dataType |
|
119
|
|
|
if ref.attrib.get('IsForward') is not None: |
|
120
|
|
|
node.parentNodeId = reference.refId |
|
121
|
|
|
node.references.append(reference) |
|
122
|
|
|
listEventType.update({node.nodeId: node}) |
|
123
|
|
|
|
|
124
|
|
|
return collections.OrderedDict( |
|
125
|
|
|
sorted(sorted(listEventType.items(), key=lambda t: t[0]), key=lambda u: len(u[0]))) |
|
126
|
|
|
|