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
|
|
|
|