backend_open62541_nodes.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. #!/usr/bin/env/python
  2. # -*- coding: utf-8 -*-
  3. ###
  4. ### Author: Chris Iatrou (ichrispa@core-vector.net)
  5. ### Version: rev 13
  6. ###
  7. ### This program was created for educational purposes and has been
  8. ### contributed to the open62541 project by the author. All licensing
  9. ### terms for this source is inherited by the terms and conditions
  10. ### specified for by the open62541 project (see the projects readme
  11. ### file for more information on the LGPL terms and restrictions).
  12. ###
  13. ### This program is not meant to be used in a production environment. The
  14. ### author is not liable for any complications arising due to the use of
  15. ### this program.
  16. ###
  17. from nodes import *
  18. from backend_open62541_datatypes import *
  19. import re
  20. import datetime
  21. ###########################################
  22. # Extract References with Special Meaning #
  23. ###########################################
  24. import logging
  25. logger = logging.getLogger(__name__)
  26. def extractNodeParent(node, parentrefs):
  27. """Return a tuple of the most likely (parent, parentReference). The
  28. parentReference is removed form the inverse references list of the node.
  29. """
  30. for ref in node.inverseReferences:
  31. if ref.referenceType in parentrefs:
  32. node.inverseReferences.remove(ref)
  33. if ref in node.printRefs:
  34. node.printRefs.remove(ref)
  35. return (ref.target, ref.referenceType)
  36. return None, None
  37. def extractNodeType(node):
  38. """Returns the most likely type of the variable- or objecttype node. The
  39. isinstanceof reference is removed form the inverse references list of the
  40. node.
  41. """
  42. pass
  43. def extractNodeSuperType(node):
  44. """Returns the most likely supertype of the variable-, object-, or referencetype
  45. node. The reference to the supertype is removed from the inverse
  46. references list of the node.
  47. """
  48. pass
  49. #################
  50. # Generate Code #
  51. #################
  52. def generateNodeIdPrintable(node):
  53. CodePrintable = "NODE_"
  54. if isinstance(node.id, NodeId):
  55. CodePrintable = node.__class__.__name__ + "_" + str(node.id)
  56. else:
  57. CodePrintable = node.__class__.__name__ + "_unknown_nid"
  58. return re.sub('[^0-9a-z_]+', '_', CodePrintable.lower())
  59. def generateNodeValueInstanceName(node, parent, recursionDepth, arrayIndex):
  60. return generateNodeIdPrintable(parent) + "_" + str(node.alias) + "_" + str(arrayIndex) + "_" + str(recursionDepth)
  61. def generateReferenceCode(reference):
  62. if reference.isForward:
  63. return "retVal |= UA_Server_addReference(server, %s, %s, %s, true);" % \
  64. (generateNodeIdCode(reference.source),
  65. generateNodeIdCode(reference.referenceType),
  66. generateExpandedNodeIdCode(reference.target))
  67. else:
  68. return "retVal |= UA_Server_addReference(server, %s, %s, %s, false);" % \
  69. (generateNodeIdCode(reference.source),
  70. generateNodeIdCode(reference.referenceType),
  71. generateExpandedNodeIdCode(reference.target))
  72. def generateReferenceTypeNodeCode(node):
  73. code = []
  74. code.append("UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;")
  75. if node.isAbstract:
  76. code.append("attr.isAbstract = true;")
  77. if node.symmetric:
  78. code.append("attr.symmetric = true;")
  79. if node.inverseName != "":
  80. code.append("attr.inverseName = UA_LOCALIZEDTEXT(\"\", \"%s\");" % \
  81. node.inverseName)
  82. return code
  83. def generateObjectNodeCode(node):
  84. code = []
  85. code.append("UA_ObjectAttributes attr = UA_ObjectAttributes_default;")
  86. if node.eventNotifier:
  87. code.append("attr.eventNotifier = true;")
  88. return code
  89. def generateVariableNodeCode(node, nodeset):
  90. code = []
  91. codeCleanup = []
  92. code.append("UA_VariableAttributes attr = UA_VariableAttributes_default;")
  93. if node.historizing:
  94. code.append("attr.historizing = true;")
  95. code.append("attr.minimumSamplingInterval = %f;" % node.minimumSamplingInterval)
  96. code.append("attr.userAccessLevel = %d;" % node.userAccessLevel)
  97. code.append("attr.accessLevel = %d;" % node.accessLevel)
  98. code.append("attr.valueRank = %d;" % node.valueRank)
  99. if node.valueRank > 0:
  100. code.append("attr.arrayDimensionsSize = %d;" % node.valueRank)
  101. code.append("attr.arrayDimensions = (UA_UInt32 *)UA_Array_new({}, &UA_TYPES[UA_TYPES_UINT32]);".format(node.valueRank))
  102. for dim in range(0, node.valueRank):
  103. code.append("attr.arrayDimensions[{}] = 0;".format(dim))
  104. if node.dataType is not None:
  105. if isinstance(node.dataType, NodeId) and node.dataType.ns == 0 and node.dataType.i == 0:
  106. #BaseDataType
  107. dataTypeNode = nodeset.nodes[NodeId("i=24")]
  108. else:
  109. dataTypeNode = nodeset.getBaseDataType(nodeset.getDataTypeNode(node.dataType))
  110. if dataTypeNode is not None:
  111. code.append("attr.dataType = %s;" % generateNodeIdCode(dataTypeNode.id))
  112. if dataTypeNode.isEncodable():
  113. if node.value is not None:
  114. [code1, codeCleanup1] = generateValueCode(node.value, nodeset.nodes[node.id], nodeset)
  115. code += code1
  116. codeCleanup += codeCleanup1
  117. else:
  118. code += generateValueCodeDummy(dataTypeNode, nodeset.nodes[node.id], nodeset)
  119. return [code, codeCleanup]
  120. def generateVariableTypeNodeCode(node, nodeset):
  121. code = []
  122. codeCleanup = []
  123. code.append("UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;")
  124. if node.historizing:
  125. code.append("attr.historizing = true;")
  126. code.append("attr.valueRank = (UA_Int32)%s;" % str(node.valueRank))
  127. if node.dataType is not None:
  128. if isinstance(node.dataType, NodeId) and node.dataType.ns == 0 and node.dataType.i == 0:
  129. #BaseDataType
  130. dataTypeNode = nodeset.nodes[NodeId("i=24")]
  131. else:
  132. dataTypeNode = nodeset.getBaseDataType(nodeset.getDataTypeNode(node.dataType))
  133. if dataTypeNode is not None:
  134. code.append("attr.dataType = %s;" % generateNodeIdCode(dataTypeNode.id))
  135. if dataTypeNode.isEncodable():
  136. if node.value is not None:
  137. [code1, codeCleanup1] = generateValueCode(node.value, nodeset.nodes[node.id], nodeset)
  138. code += code1
  139. codeCleanup += codeCleanup1
  140. else:
  141. code += generateValueCodeDummy(dataTypeNode, nodeset.nodes[node.id], nodeset)
  142. return [code, codeCleanup]
  143. def generateExtensionObjectSubtypeCode(node, parent, nodeset, recursionDepth=0, arrayIndex=0):
  144. code = [""]
  145. codeCleanup = [""]
  146. logger.debug("Building extensionObject for " + str(parent.id))
  147. logger.debug("Value " + str(node.value))
  148. logger.debug("Encoding " + str(node.encodingRule))
  149. instanceName = generateNodeValueInstanceName(node, parent, recursionDepth, arrayIndex)
  150. # If there are any ExtensionObjects instide this ExtensionObject, we need to
  151. # generate one-time-structs for them too before we can proceed;
  152. for subv in node.value:
  153. if isinstance(subv, list):
  154. logger.error("ExtensionObject contains an ExtensionObject, which is currently not encodable!")
  155. code.append("struct {")
  156. for field in node.encodingRule:
  157. ptrSym = ""
  158. # If this is an Array, this is pointer to its contents with a AliasOfFieldSize entry
  159. if field[2] != 0:
  160. code.append(" UA_Int32 " + str(field[0]) + "Size;")
  161. ptrSym = "*"
  162. if len(field[1]) == 1:
  163. code.append(" UA_" + str(field[1][0]) + " " + ptrSym + str(field[0]) + ";")
  164. else:
  165. code.append(" UA_ExtensionObject " + " " + ptrSym + str(field[0]) + ";")
  166. code.append("} " + instanceName + "_struct;")
  167. # Assign data to the struct contents
  168. # Track the encoding rule definition to detect arrays and/or ExtensionObjects
  169. encFieldIdx = 0
  170. for subv in node.value:
  171. encField = node.encodingRule[encFieldIdx]
  172. encFieldIdx = encFieldIdx + 1
  173. logger.debug(
  174. "Encoding of field " + subv.alias + " is " + str(subv.encodingRule) + "defined by " + str(encField))
  175. # Check if this is an array
  176. if encField[2] == 0:
  177. code.append(instanceName + "_struct." + subv.alias + " = " +
  178. generateNodeValueCode(subv, instanceName, asIndirect=False) + ";")
  179. else:
  180. if isinstance(subv, list):
  181. # this is an array
  182. code.append(instanceName + "_struct." + subv.alias + "Size = " + str(len(subv)) + ";")
  183. code.append(
  184. instanceName + "_struct." + subv.alias + " = (UA_" + subv.__class__.__name__ +
  185. " *) UA_malloc(sizeof(UA_" + subv.__class__.__name__ + ")*" + str(
  186. len(subv)) + ");")
  187. logger.debug("Encoding included array of " + str(len(subv)) + " values.")
  188. for subvidx in range(0, len(subv)):
  189. subvv = subv[subvidx]
  190. logger.debug(" " + str(subvidx) + " " + str(subvv))
  191. code.append(instanceName + "_struct." + subv.alias + "[" + str(
  192. subvidx) + "] = " + generateNodeValueCode(subvv, instanceName) + ";")
  193. code.append("}")
  194. else:
  195. code.append(instanceName + "_struct." + subv.alias + "Size = 1;")
  196. code.append(
  197. instanceName + "_struct." + subv.alias + " = (UA_" + subv.__class__.__name__ +
  198. " *) UA_malloc(sizeof(UA_" + subv.__class__.__name__ + "));")
  199. code.append(instanceName + "_struct." + subv.alias + "[0] = " +
  200. generateNodeValueCode(subv, instanceName, asIndirect=True) + ";")
  201. # Allocate some memory
  202. code.append("UA_ExtensionObject *" + instanceName + " = UA_ExtensionObject_new();")
  203. codeCleanup.append("UA_ExtensionObject_delete(" + instanceName + ");")
  204. code.append(instanceName + "->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;")
  205. #if parent.dataType.ns == 0:
  206. binaryEncodingId = nodeset.getBinaryEncodingIdForNode(parent.dataType)
  207. code.append(
  208. instanceName + "->content.encoded.typeId = UA_NODEID_NUMERIC(" + str(binaryEncodingId.ns) + ", " +
  209. str(binaryEncodingId.i) + ");")
  210. code.append(
  211. "if(UA_ByteString_allocBuffer(&" + instanceName + "->content.encoded.body, 65000) != UA_STATUSCODE_GOOD) {}")
  212. # Encode each value as a bytestring seperately.
  213. code.append("UA_Byte *pos" + instanceName + " = " + instanceName + "->content.encoded.body.data;")
  214. code.append("const UA_Byte *end" + instanceName + " = &" + instanceName + "->content.encoded.body.data[65000];")
  215. encFieldIdx = 0
  216. code.append("{")
  217. for subv in node.value:
  218. encField = node.encodingRule[encFieldIdx]
  219. encFieldIdx = encFieldIdx + 1
  220. if encField[2] == 0:
  221. code.append(
  222. "retVal |= UA_encodeBinary(&" + instanceName + "_struct." + subv.alias + ", " +
  223. getTypesArrayForValue(nodeset, subv) + ", &pos" + instanceName + ", &end" + instanceName + ", NULL, NULL);")
  224. else:
  225. if isinstance(subv, list):
  226. for subvidx in range(0, len(subv)):
  227. code.append("retVal |= UA_encodeBinary(&" + instanceName + "_struct." + subv.alias + "[" +
  228. str(subvidx) + "], " + getTypesArrayForValue(nodeset, subv) + ", &pos" +
  229. instanceName + ", &end" + instanceName + ", NULL, NULL);")
  230. else:
  231. code.append(
  232. "retVal |= UA_encodeBinary(&" + instanceName + "_struct." + subv.alias + "[0], " +
  233. getTypesArrayForValue(nodeset, subv) + ", &pos" + instanceName + ", &end" + instanceName + ", NULL, NULL);")
  234. code.append("}")
  235. # Reallocate the memory by swapping the 65k Bytestring for a new one
  236. code.append("size_t " + instanceName + "_encOffset = (uintptr_t)(" +
  237. "pos" + instanceName + "-" + instanceName + "->content.encoded.body.data);")
  238. code.append(instanceName + "->content.encoded.body.length = " + instanceName + "_encOffset;")
  239. code.append("UA_Byte *" + instanceName + "_newBody = (UA_Byte *) UA_malloc(" + instanceName + "_encOffset );")
  240. code.append("memcpy(" + instanceName + "_newBody, " + instanceName + "->content.encoded.body.data, " +
  241. instanceName + "_encOffset);")
  242. code.append("UA_Byte *" + instanceName + "_oldBody = " + instanceName + "->content.encoded.body.data;")
  243. code.append(instanceName + "->content.encoded.body.data = " + instanceName + "_newBody;")
  244. code.append("UA_free(" + instanceName + "_oldBody);")
  245. code.append("")
  246. return [code, codeCleanup]
  247. def generateValueCodeDummy(dataTypeNode, parentNode, nodeset, bootstrapping=True):
  248. code = []
  249. valueName = generateNodeIdPrintable(parentNode) + "_variant_DataContents"
  250. typeArr = dataTypeNode.typesArray + "[" + dataTypeNode.typesArray + "_" + dataTypeNode.browseName.name.upper() + "]"
  251. typeStr = "UA_" + dataTypeNode.browseName.name
  252. if parentNode.valueRank > 0:
  253. code.append(typeStr + " *" + valueName + " = (" + typeStr + "*) UA_alloca(" + typeArr + ".memSize * " + str(parentNode.valueRank) + ");")
  254. for i in range(0, parentNode.valueRank):
  255. code.append("UA_init(&" + valueName + "[" + str(i) + "], &" + typeArr + ");")
  256. code.append("UA_Variant_setArray( &attr.value, " + valueName + ", (UA_Int32) " +
  257. str(parentNode.valueRank) + ", &" + typeArr + ");")
  258. else:
  259. code.append("void *" + valueName + " = UA_alloca(" + typeArr + ".memSize);")
  260. code.append("UA_init(" + valueName + ", &" + typeArr + ");")
  261. code.append("UA_Variant_setScalar(&attr.value, " + valueName + ", &" + typeArr + ");")
  262. return code
  263. def getTypesArrayForValue(nodeset, value):
  264. typeNode = nodeset.getNodeByBrowseName(value.__class__.__name__)
  265. if typeNode is None:
  266. typesArray = "UA_TYPES"
  267. else:
  268. typesArray = typeNode.typesArray
  269. return "&" + typesArray + "[" + typesArray + "_" + \
  270. value.__class__.__name__.upper() + "]"
  271. def generateValueCode(node, parentNode, nodeset, bootstrapping=True):
  272. code = []
  273. codeCleanup = []
  274. valueName = generateNodeIdPrintable(parentNode) + "_variant_DataContents"
  275. # node.value either contains a list of multiple identical BUILTINTYPES, or it
  276. # contains a single builtintype (which may be a container); choose if we need
  277. # to create an array or a single variable.
  278. # Note that some genious defined that there are arrays of size 1, which are
  279. # distinctly different then a single value, so we need to check that as well
  280. # Semantics:
  281. # -3: Scalar or 1-dim
  282. # -2: Scalar or x-dim | x>0
  283. # -1: Scalar
  284. # 0: x-dim | x>0
  285. # n: n-dim | n>0
  286. if (len(node.value) == 0):
  287. return ""
  288. if not isinstance(node.value[0], Value):
  289. return ""
  290. if parentNode.valueRank != -1 and (parentNode.valueRank >= 0
  291. or (len(node.value) > 1
  292. and (parentNode.valueRank != -2 or parentNode.valueRank != -3))):
  293. # User the following strategy for all directly mappable values a la 'UA_Type MyInt = (UA_Type) 23;'
  294. if node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_GUID:
  295. logger.warn("Don't know how to print array of GUID in node " + str(parentNode.id))
  296. elif node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_DATETIME:
  297. logger.warn("Don't know how to print array of DateTime in node " + str(parentNode.id))
  298. elif node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_DIAGNOSTICINFO:
  299. logger.warn("Don't know how to print array of DiagnosticInfo in node " + str(parentNode.id))
  300. elif node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_STATUSCODE:
  301. logger.warn("Don't know how to print array of StatusCode in node " + str(parentNode.id))
  302. else:
  303. if node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_EXTENSIONOBJECT:
  304. for idx, v in enumerate(node.value):
  305. logger.debug("Building extObj array index " + str(idx))
  306. [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(v, parent=parentNode, nodeset=nodeset, arrayIndex=idx)
  307. code = code + code1
  308. codeCleanup = codeCleanup + codeCleanup1
  309. code.append("UA_" + node.value[0].__class__.__name__ + " " + valueName + "[" + str(len(node.value)) + "];")
  310. if node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_EXTENSIONOBJECT:
  311. for idx, v in enumerate(node.value):
  312. logger.debug("Printing extObj array index " + str(idx))
  313. instanceName = generateNodeValueInstanceName(v, parentNode, 0, idx)
  314. code.append(
  315. valueName + "[" + str(idx) + "] = " +
  316. generateNodeValueCode(v, instanceName) + ";")
  317. # code.append("UA_free(&" +valueName + "[" + str(idx) + "]);")
  318. else:
  319. for idx, v in enumerate(node.value):
  320. instanceName = generateNodeValueInstanceName(v, parentNode, 0, idx)
  321. code.append(
  322. valueName + "[" + str(idx) + "] = " + generateNodeValueCode(v, instanceName) + ";")
  323. code.append("UA_Variant_setArray( &attr.value, &" + valueName +
  324. ", (UA_Int32) " + str(len(node.value)) + ", " +
  325. getTypesArrayForValue(nodeset, node.value[0]) + ");")
  326. else:
  327. # User the following strategy for all directly mappable values a la 'UA_Type MyInt = (UA_Type) 23;'
  328. if node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_GUID:
  329. logger.warn("Don't know how to print scalar GUID in node " + str(parentNode.id))
  330. elif node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_DATETIME:
  331. logger.warn("Don't know how to print scalar DateTime in node " + str(parentNode.id))
  332. elif node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_DIAGNOSTICINFO:
  333. logger.warn("Don't know how to print scalar DiagnosticInfo in node " + str(parentNode.id))
  334. elif node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_STATUSCODE:
  335. logger.warn("Don't know how to print scalar StatusCode in node " + str(parentNode.id))
  336. else:
  337. # The following strategy applies to all other types, in particular strings and numerics.
  338. if node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_EXTENSIONOBJECT:
  339. [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(node.value[0], parent=parentNode, nodeset=nodeset)
  340. code = code + code1
  341. codeCleanup = codeCleanup + codeCleanup1
  342. instanceName = generateNodeValueInstanceName(node.value[0], parentNode, 0, 0)
  343. if node.value[0].numericRepresentation == BUILTINTYPE_TYPEID_EXTENSIONOBJECT:
  344. code.append("UA_" + node.value[0].__class__.__name__ + " *" + valueName + " = " +
  345. generateNodeValueCode(node.value[0], instanceName) + ";")
  346. code.append(
  347. "UA_Variant_setScalar( &attr.value, " + valueName + ", " +
  348. getTypesArrayForValue(nodeset, node.value[0]) + ");")
  349. # FIXME: There is no membership definition for extensionObjects generated in this function.
  350. # code.append("UA_" + node.value[0].__class__.__name__ + "_deleteMembers(" + valueName + ");")
  351. else:
  352. code.append("UA_" + node.value[0].__class__.__name__ + " *" + valueName + " = UA_" + node.value[
  353. 0].__class__.__name__ + "_new();")
  354. code.append("*" + valueName + " = " + generateNodeValueCode(node.value[0], instanceName) + ";")
  355. code.append(
  356. "UA_Variant_setScalar( &attr.value, " + valueName + ", " +
  357. getTypesArrayForValue(nodeset, node.value[0]) + ");")
  358. return [code, codeCleanup]
  359. def generateMethodNodeCode(node):
  360. code = []
  361. code.append("UA_MethodAttributes attr = UA_MethodAttributes_default;")
  362. if node.executable:
  363. code.append("attr.executable = true;")
  364. if node.userExecutable:
  365. code.append("attr.userExecutable = true;")
  366. return code
  367. def generateObjectTypeNodeCode(node):
  368. code = []
  369. code.append("UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;")
  370. if node.isAbstract:
  371. code.append("attr.isAbstract = true;")
  372. return code
  373. def generateDataTypeNodeCode(node):
  374. code = []
  375. code.append("UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;")
  376. if node.isAbstract:
  377. code.append("attr.isAbstract = true;")
  378. return code
  379. def generateViewNodeCode(node):
  380. code = []
  381. code.append("UA_ViewAttributes attr = UA_ViewAttributes_default;")
  382. if node.containsNoLoops:
  383. code.append("attr.containsNoLoops = true;")
  384. code.append("attr.eventNotifier = (UA_Byte)%s;" % str(node.eventNotifier))
  385. return code
  386. def getNodeTypeDefinition(node):
  387. for ref in node.references:
  388. # 40 = HasTypeDefinition
  389. if ref.referenceType.i == 40:
  390. return ref.target
  391. return None
  392. def generateSubtypeOfDefinitionCode(node):
  393. for ref in node.inverseReferences:
  394. # 45 = HasSubtype
  395. if ref.referenceType.i == 45:
  396. return generateNodeIdCode(ref.target)
  397. return "UA_NODEID_NULL"
  398. def generateNodeCode(node, supressGenerationOfAttribute, generate_ns0, parentrefs, nodeset):
  399. code = []
  400. code.append("{")
  401. codeCleanup = []
  402. if isinstance(node, ReferenceTypeNode):
  403. code.extend(generateReferenceTypeNodeCode(node))
  404. elif isinstance(node, ObjectNode):
  405. code.extend(generateObjectNodeCode(node))
  406. elif isinstance(node, VariableNode) and not isinstance(node, VariableTypeNode):
  407. [code1, codeCleanup1] = generateVariableNodeCode(node, nodeset)
  408. code.extend(code1)
  409. codeCleanup.extend(codeCleanup1)
  410. elif isinstance(node, VariableTypeNode):
  411. [code1, codeCleanup1] = generateVariableTypeNodeCode(node, nodeset)
  412. code.extend(code1)
  413. codeCleanup.extend(codeCleanup1)
  414. elif isinstance(node, MethodNode):
  415. code.extend(generateMethodNodeCode(node))
  416. elif isinstance(node, ObjectTypeNode):
  417. code.extend(generateObjectTypeNodeCode(node))
  418. elif isinstance(node, DataTypeNode):
  419. code.extend(generateDataTypeNodeCode(node))
  420. elif isinstance(node, ViewNode):
  421. code.extend(generateViewNodeCode(node))
  422. code.append("attr.displayName = " + generateLocalizedTextCode(node.displayName) + ";")
  423. code.append("attr.description = " + generateLocalizedTextCode(node.description) + ";")
  424. code.append("attr.writeMask = %d;" % node.writeMask)
  425. code.append("attr.userWriteMask = %d;" % node.userWriteMask)
  426. typeDef = getNodeTypeDefinition(node)
  427. isDataTypeEncodingType = typeDef is not None and typeDef.ns == 0 and typeDef.i == 76
  428. # Object nodes of type DataTypeEncoding do not have any parent
  429. if not generate_ns0 and not isDataTypeEncodingType:
  430. (parentNode, parentRef) = extractNodeParent(node, parentrefs)
  431. if parentNode is None or parentRef is None:
  432. return None
  433. else:
  434. (parentNode, parentRef) = (NodeId(), NodeId())
  435. code.append("retVal |= UA_Server_add%s(server," % node.__class__.__name__)
  436. code.append(generateNodeIdCode(node.id) + ",")
  437. code.append(generateNodeIdCode(parentNode) + ",")
  438. code.append(generateNodeIdCode(parentRef) + ",")
  439. code.append(generateQualifiedNameCode(node.browseName) + ",")
  440. if isinstance(node, VariableTypeNode):
  441. # we need the HasSubtype reference
  442. code.append(generateSubtypeOfDefinitionCode(node) + ",")
  443. elif isinstance(node, VariableNode) or isinstance(node, ObjectNode):
  444. typeDefCode = "UA_NODEID_NULL" if typeDef is None else generateNodeIdCode(typeDef)
  445. code.append(typeDefCode + ",")
  446. code.append("attr,")
  447. if isinstance(node, MethodNode):
  448. code.append("NULL, 0, NULL, 0, NULL, NULL, NULL);")
  449. else:
  450. code.append("NULL, NULL);")
  451. code.extend(codeCleanup)
  452. code.append("}\n")
  453. return "\n".join(code)