2 Generate address space c++ code from xml file specification 7 import xml.etree.ElementTree
as ET
17 NoSplitStruct = [
"GetEndpointsResponse",
"CloseSessionRequest",
"AddNodesResponse",
"DeleteNodesResponse",
"BrowseResponse",
"HistoryReadResponse",
"HistoryUpdateResponse",
"RegisterServerResponse",
"CloseSecureChannelRequest",
"CloseSecureChannelResponse",
"CloseSessionRequest",
"CloseSessionResponse",
"UnregisterNodesResponse",
"MonitoredItemModifyRequest",
"MonitoredItemsCreateRequest",
"ReadResponse",
"WriteResponse",
"TranslateBrowsePathsToNodeIdsResponse",
"DeleteSubscriptionsResponse",
"DeleteMonitoredItemsResponse",
"CreateMonitoredItemsResponse",
"ServiceFault",
"AddReferencesRequest",
"AddReferencesResponse",
"ModifyMonitoredItemsResponse",
"RepublishResponse",
"CallResponse",
"FindServersResponse",
"RegisterServerRequest",
"RegisterServer2Response"]
19 NotRequest = [
"MonitoredItemCreateRequest",
"MonitoredItemModifyRequest",
"CallMethodRequest"]
36 return "(Bit: {0}, container:{1}, idx:{2})".format(self.
name, self.
container, self.
idx)
56 raise Exception(
"field not found: " + name)
75 return "Field {0}({1})".format(self.
name, self.
uatype)
80 if self.
uatype in (
"Char",
"SByte",
"Int8",
"Int16",
"Int32",
"Int64",
"UInt8",
"UInt16",
"UInt32",
"UInt64",
"Boolean",
"Double",
"Float",
"Byte",
"String",
"CharArray",
"ByteString",
"DateTime"):
85 if self.
uatype ==
"String":
87 elif self.
uatype ==
"CharArray":
89 elif self.
uatype ==
"Char":
91 elif self.
uatype ==
"SByte":
93 elif self.
uatype ==
"Int8":
95 elif self.
uatype ==
"Int16":
97 elif self.
uatype ==
"Int32":
99 elif self.
uatype ==
"Int64":
101 elif self.
uatype ==
"UInt8":
103 elif self.
uatype ==
"UInt16":
105 elif self.
uatype ==
"UInt32":
107 elif self.
uatype ==
"UInt64":
109 elif self.
uatype ==
"DateTime":
110 ty =
"OpcUa::DateTime" 111 elif self.
uatype ==
"Boolean":
113 elif self.
uatype ==
"Double":
115 elif self.
uatype ==
"Float":
117 elif self.
uatype ==
"ByteString":
118 ty =
"OpcUa::ByteString" 119 elif self.
uatype ==
"Byte":
122 ty =
"OpcUa::" + self.
uatype 124 ty =
"std::vector<{0}>".format(ty)
135 return "uint{0}_t".format(self.
uatype)
151 if name == struct.name:
153 raise Exception(
"No struct named: " + str(name))
159 raise Exception(
"No enum named: " + str(name))
165 types = IgnoredStructs + IgnoredEnums + [
"Bit",
"Char",
"CharArray",
"Guid",
"SByte",
"Int8",
"Int16",
"Int32",
"Int64",
"UInt8",
"UInt16",
"UInt32",
"UInt64",
"DateTime",
"Boolean",
"Double",
"Float",
"ByteString",
"Byte",
"StatusCode",
"DiagnosticInfo",
"String",
"AttributeID"] + [enum.name
for enum
in model.enums] + [
"VariableAccessLevel"]
168 for s
in model.structs:
173 if f.uatype
not in types:
174 if f.uatype
in waiting.keys():
175 waiting[f.uatype].append(s)
176 s.waitingfor.append(f.uatype)
178 waiting[f.uatype] = [s]
179 s.waitingfor.append(f.uatype)
183 waitings = waiting.pop(s.name,
None)
186 s2.waitingfor.remove(s.name)
187 if not s2.waitingfor:
188 newstructs.append(s2)
189 if len(model.structs) != len(newstructs):
190 print(
"Error while reordering structs, some structs could not be reinserted, had {0} structs, we now have {1} structs".format(len(model.structs), len(newstructs)))
191 s1 = set(model.structs)
194 print(
"Variant" in types)
196 print(
"{0} is waiting for: {1}".format(s, s.waitingfor))
199 model.structs = newstructs
202 for struct
in model.structs:
203 for field
in struct.fields:
204 if field.name
in OverrideTypes.keys():
205 field.uatype = OverrideTypes[field.name]
208 for struct
in model.structs:
211 for field
in struct.fields:
212 if field.name
not in names:
213 names.append(field.name)
215 struct.fields = fields
218 for struct
in model.structs:
222 for field
in struct.fields:
223 if field.uatype
in (
"UInt6",
"NodeIdType"):
224 container = field.name
228 b.container = container
231 struct.bits[b.name] = b
233 if field.uatype ==
"Bit":
234 if not container
or idx > 7:
235 container =
"Encoding" 238 f.sourcetype = field.sourcetype
246 b.container = container
247 b.length = field.bitlength
248 idx += field.bitlength
249 struct.bits[b.name] = b
251 newfields.append(field)
252 struct.fields = newfields
255 for struct
in model.structs:
257 for field
in struct.fields:
258 if not field.name.startswith(
"NoOf"):
263 for struct
in model.structs:
265 for field
in struct.fields:
266 if not field.name ==
"BodyLength":
277 for struct
in model.structs:
279 if struct.name.endswith(
"Request")
and not struct.name
in NotRequest:
280 structtype =
"Request" 281 elif struct.name.endswith(
"Response")
or struct.name ==
"ServiceFault":
282 structtype =
"Response" 292 struct.needconstructor =
True 294 field.name =
"TypeId" 295 field.uatype =
"NodeId" 296 struct.fields.insert(0, field)
298 if structtype
and not struct.name
in NoSplitStruct:
300 if structtype ==
"Request":
301 basename = struct.name.replace(
"Request",
"") +
"Parameters" 302 paramstruct.name = basename
304 basename = struct.name.replace(
"Response",
"") +
"Result" 305 paramstruct.name = basename
306 paramstruct.fields = struct.fields[2:]
307 paramstruct.bits = struct.bits
309 struct.fields = struct.fields[:2]
311 structs.append(paramstruct)
314 typeid.name =
"Parameters" 315 typeid.uatype = paramstruct.name
316 struct.fields.append(typeid)
317 structs.append(struct)
318 model.structs = structs
327 print(
"Parsing: ", self.
path)
329 tree = ET.parse(self.
path)
330 root = tree.getroot()
334 if tag ==
"StructuredType":
336 if struct.name !=
"ExtensionObject":
337 self.model.structs.append(struct)
338 self.model.struct_list.append(struct.name)
339 elif tag ==
"EnumeratedType":
341 self.model.enums.append(enum)
342 self.model.enum_list.append(enum.name)
349 obj.name =
"ExtensionObject" 355 f.name =
"BinaryBody" 364 f.uatype =
"ByteString" 365 f.switchfield =
"BinaryBody" 367 self.model.struct_list.append(obj.name)
369 self.model.structs.append(obj)
374 for key, val
in child.attrib.items():
377 elif key ==
"BaseType":
379 prefix, val = val.split(
":")
380 struct.basetype = val
383 struct.parents.append(tmp.basetype)
384 tmp = self.model.get_struct(tmp.basetype)
386 print(
"Error unknown key: ", key)
391 for key, val
in el.attrib.items():
394 elif key ==
"TypeName":
395 field.uatype = val.split(
":")[1]
396 elif key ==
"LengthField":
398 elif key ==
"SourceType":
399 field.sourcetype = val
400 elif key ==
"SwitchField":
401 field.switchfield = val
402 elif key ==
"SwitchValue":
403 field.switchvalue = val
404 elif key ==
"Length":
405 field.bitlength = int(val)
407 print(
"Unknown field item: ", struct.name, key)
409 struct.fields.append(field)
410 elif tag ==
"Documentation":
413 print(
"Unknown tag: ", tag)
420 for k, v
in child.items():
423 elif k ==
"LengthInBits":
424 enum.uatype =
"UInt" + v
426 print(
"Unknown attr for enum: ", k)
429 if tag ==
"EnumeratedValue":
431 for k, v
in el.attrib.items():
437 print(
"Unknown field attrib: ", k)
438 enum.values.append(ev)
439 elif tag ==
"Documentation":
442 print(
"Unknown enum tag: ", tag)
454 for struct
in model.structs:
455 if not struct.basetype:
458 if len(struct.fields) == 0:
460 if struct.basetype
in (
"ExtensionObject"):
461 struct.basetype =
None 463 base = model.get_struct(struct.basetype)
474 for name, bit
in base.bits.items():
475 struct.bits[name] = bit
476 for idx, field
in enumerate(base.fields):
478 if field.name ==
"Body" and not emptystruct:
480 struct.extensionobject =
True 481 field.name =
"BodyLength" 482 field.uatype =
"Int32" 484 field.switchfield =
None 496 if not field.sourcetype:
497 field.sourcetype = base.name
498 struct.fields.insert(idx, field)
def split_requests(model)
def override_types(model)
def parse_enum(self, child)
def remove_duplicates(model)
def add_basetype_members(model)
def get_struct(self, name)
def remove_body_length(model)
def add_encoding_field(model)
def remove_vector_length(model)
def parse_struct(self, child)
def add_extension_object(self)
def get_field(self, name)
def reorder_structs(model)