ua_builtin_types.py 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  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. import xml.dom.minidom as dom
  18. from ua_constants import *
  19. from logger import *
  20. from open62541_MacroHelper import open62541_MacroHelper
  21. def getNextElementNode(xmlvalue):
  22. if xmlvalue == None:
  23. return None
  24. xmlvalue = xmlvalue.nextSibling
  25. while not xmlvalue == None and not xmlvalue.nodeType == xmlvalue.ELEMENT_NODE:
  26. xmlvalue = xmlvalue.nextSibling
  27. return xmlvalue
  28. class opcua_value_t():
  29. value = None
  30. name = None
  31. __alias__ = None
  32. __binTypeId__ = 0
  33. stringRepresentation = ""
  34. knownTypes = []
  35. parent = None
  36. def __init__(self, parent):
  37. self.value = None
  38. self.parent = parent
  39. self.stringRepresentation = ""
  40. self.setStringReprentation()
  41. self.__binTypeId__ = 0
  42. self.setNumericRepresentation()
  43. self.__alias__ = None
  44. self.knownTypes = ['boolean', 'int32', 'uint32', 'int16', 'uint16', \
  45. 'int64', 'uint64', 'byte', 'sbyte', 'float', 'double', \
  46. 'string', 'bytestring', 'localizedtext', 'statuscode', \
  47. 'diagnosticinfo', 'nodeid', 'guid', 'datetime', \
  48. 'qualifiedname', 'expandednodeid', 'xmlelement']
  49. self.dataType = None
  50. self.encodingRule = []
  51. def setEncodingRule(self, encoding):
  52. self.encodingRule = encoding
  53. def getEncodingRule(self):
  54. return self.encodingRule
  55. def alias(self, data=None):
  56. if not data == None:
  57. self.__alias__ = data
  58. return self.__alias__
  59. def isBuiltinByString(self, string):
  60. if str(string).lower() in self.knownTypes:
  61. return True
  62. return False
  63. def value(self, data=None):
  64. if not data==None:
  65. self.__value__ = data
  66. return self.__value__
  67. def getTypeByString(self, stringName, encodingRule):
  68. stringName = str(stringName.lower())
  69. if stringName == 'boolean':
  70. t = opcua_BuiltinType_boolean_t(self.parent)
  71. t.setEncodingRule(encodingRule)
  72. elif stringName == 'int32':
  73. t = opcua_BuiltinType_int32_t(self.parent)
  74. t.setEncodingRule(encodingRule)
  75. elif stringName == 'uint32':
  76. t = opcua_BuiltinType_uint32_t(self.parent)
  77. t.setEncodingRule(encodingRule)
  78. elif stringName == 'int16':
  79. t = opcua_BuiltinType_int16_t(self.parent)
  80. t.setEncodingRule(encodingRule)
  81. elif stringName == 'uint16':
  82. t = opcua_BuiltinType_uint16_t(self.parent)
  83. t.setEncodingRule(encodingRule)
  84. elif stringName == 'int64':
  85. t = opcua_BuiltinType_int64_t(self.parent)
  86. t.setEncodingRule(encodingRule)
  87. elif stringName == 'uint64':
  88. t = opcua_BuiltinType_uint64_t(self.parent)
  89. t.setEncodingRule(encodingRule)
  90. elif stringName == 'byte':
  91. t = opcua_BuiltinType_byte_t(self.parent)
  92. t.setEncodingRule(encodingRule)
  93. elif stringName == 'sbyte':
  94. t = opcua_BuiltinType_sbyte_t(self.parent)
  95. t.setEncodingRule(encodingRule)
  96. elif stringName == 'float':
  97. t = opcua_BuiltinType_float_t(self.parent)
  98. t.setEncodingRule(encodingRule)
  99. elif stringName == 'double':
  100. t = opcua_BuiltinType_double_t(self.parent)
  101. t.setEncodingRule(encodingRule)
  102. elif stringName == 'string':
  103. t = opcua_BuiltinType_string_t(self.parent)
  104. t.setEncodingRule(encodingRule)
  105. elif stringName == 'bytestring':
  106. t = opcua_BuiltinType_bytestring_t(self.parent)
  107. t.setEncodingRule(encodingRule)
  108. elif stringName == 'localizedtext':
  109. t = opcua_BuiltinType_localizedtext_t(self.parent)
  110. t.setEncodingRule(encodingRule)
  111. elif stringName == 'statuscode':
  112. t = opcua_BuiltinType_statuscode_t(self.parent)
  113. t.setEncodingRule(encodingRule)
  114. elif stringName == 'diagnosticinfo':
  115. t = opcua_BuiltinType_diagnosticinfo_t(self.parent)
  116. t.setEncodingRule(encodingRule)
  117. elif stringName == 'nodeid':
  118. t = opcua_BuiltinType_nodeid_t(self.parent)
  119. t.setEncodingRule(encodingRule)
  120. elif stringName == 'guid':
  121. t = opcua_BuiltinType_guid_t(self.parent)
  122. t.setEncodingRule(encodingRule)
  123. elif stringName == 'datetime':
  124. t = opcua_BuiltinType_datetime_t(self.parent)
  125. t.setEncodingRule(encodingRule)
  126. elif stringName == 'qualifiedname':
  127. t = opcua_BuiltinType_qualifiedname_t(self.parent)
  128. t.setEncodingRule(encodingRule)
  129. elif stringName == 'expandednodeid':
  130. t = opcua_BuiltinType_expandednodeid_t(self.parent)
  131. t.setEncodingRule(encodingRule)
  132. elif stringName == 'xmlelement':
  133. t = opcua_BuiltinType_xmlelement_t(self.parent)
  134. t.setEncodingRule(encodingRule)
  135. else:
  136. log(self, "No class representing stringName " + stringName + " was found. Cannot create builtinType.")
  137. return None
  138. return t
  139. def parseXML(self, xmlvalue):
  140. log(self, "parsing xmlvalue for " + self.parent.browseName() + " (" + str(self.parent.id()) + ") according to " + str(self.parent.dataType().target().getEncoding()))
  141. if not "value" in xmlvalue.tagName.lower():
  142. log(self, "Expected <Value> , but found " + xmlvalue.tagName + " instead. Value will not be parsed.", LOG_LEVEL_ERROR)
  143. return
  144. if len(xmlvalue.childNodes) == 0:
  145. log(self, "Expected childnodes for value, but none where found... Value will not be parsed.", LOG_LEVEL_ERROR)
  146. return
  147. for n in xmlvalue.childNodes:
  148. if n.nodeType == n.ELEMENT_NODE:
  149. xmlvalue = n
  150. break
  151. if "ListOf" in xmlvalue.tagName:
  152. self.value = []
  153. for el in xmlvalue.childNodes:
  154. if not el.nodeType == el.ELEMENT_NODE:
  155. continue
  156. self.value.append(self.__parseXMLSingleValue(el))
  157. else:
  158. self.value = [self.__parseXMLSingleValue(xmlvalue)]
  159. log(self, "Parsed Value: " + str(self.value))
  160. def __parseXMLSingleValue(self, xmlvalue, alias=None, encodingPart=None):
  161. # Parse an encoding list such as enc = [[Int32], ['Duration', ['DateTime']]],
  162. # returning a possibly aliased variable or list of variables.
  163. # Keep track of aliases, as ['Duration', ['Hawaii', ['UtcTime', ['DateTime']]]]
  164. # will be of type DateTime, but tagged as <Duration>2013-04-10 12:00 UTC</Duration>,
  165. # and not as <Duration><Hawaii><UtcTime><String>2013-04-10 12:00 UTC</String>...
  166. # Encoding may be partially handed down (iterative call). Only resort to
  167. # type definition if we are not given a specific encoding to match
  168. if encodingPart == None:
  169. enc = self.parent.dataType().target().getEncoding()
  170. else:
  171. enc = encodingPart
  172. # Check the structure of the encoding list to determine if a type is to be
  173. # returned or we need to descend further checking aliases or multipart types
  174. # such as extension Objects.
  175. if len(enc) == 1:
  176. # 0: ['BuiltinType'] either builtin type
  177. # 1: [ [ 'Alias', [...], n] ] or single alias for possible multipart
  178. if isinstance(enc[0], str):
  179. # 0: 'BuiltinType'
  180. if alias != None:
  181. if not xmlvalue.tagName == alias:
  182. log(self, "Expected XML element with tag " + alias + " but found " + xmlvalue.tagName + " instead", LOG_LEVEL_ERROR)
  183. return None
  184. else:
  185. t = self.getTypeByString(enc[0], enc)
  186. t.alias(alias)
  187. t.parseXML(xmlvalue)
  188. return t
  189. else:
  190. if not self.isBuiltinByString(xmlvalue.tagName):
  191. log(self, "Expected XML describing builtin type " + enc[0] + " but found " + xmlvalue.tagName + " instead", LOG_LEVEL_ERROR)
  192. else:
  193. t = self.getTypeByString(enc[0], enc)
  194. t.parseXML(xmlvalue)
  195. return t
  196. else:
  197. # 1: ['Alias', [...], n]
  198. # Let the next elif handle this
  199. return self.__parseXMLSingleValue(xmlvalue, alias=alias, encodingPart=enc[0])
  200. elif len(enc) == 3 and isinstance(enc[0], str):
  201. # [ 'Alias', [...], 0 ] aliased multipart
  202. if alias == None:
  203. alias = enc[0]
  204. # if we have an alias and the next field is multipart, keep the alias
  205. elif alias != None and len(enc[1]) > 1:
  206. alias = enc[0]
  207. # otherwise drop the alias
  208. return self.__parseXMLSingleValue(xmlvalue, alias=alias, encodingPart=enc[1])
  209. else:
  210. # [ [...], [...], [...]] multifield of unknowns (analyse separately)
  211. # create an extension object to hold multipart type
  212. # FIXME: This implementation expects an extensionobject to be manditory for
  213. # multipart variables. Variants/Structures are not included in the
  214. # OPCUA Namespace 0 nodeset.
  215. # Consider moving this ExtensionObject specific parsing into the
  216. # builtin type and only determining the multipart type at this stage.
  217. if not xmlvalue.tagName == "ExtensionObject":
  218. log(self, "Expected XML tag <ExtensionObject> for multipart type, but found " + xmlvalue.tagName + " instead.", LOG_LEVEL_ERROR)
  219. return None
  220. extobj = opcua_BuiltinType_extensionObject_t(self.parent)
  221. extobj.setEncodingRule(enc)
  222. etype = xmlvalue.getElementsByTagName("TypeId")
  223. if len(etype) == 0:
  224. log(self, "Did not find <TypeId> for ExtensionObject", LOG_LEVEL_ERROR)
  225. return None
  226. etype = etype[0].getElementsByTagName("Identifier")
  227. if len(etype) == 0:
  228. log(self, "Did not find <Identifier> for ExtensionObject", LOG_LEVEL_ERROR)
  229. return None
  230. etype = self.parent.getNamespace().getNodeByIDString(etype[0].firstChild.data)
  231. if etype == None:
  232. log(self, "Identifier Node not found in namespace" , LOG_LEVEL_ERROR)
  233. return None
  234. extobj.typeId(etype)
  235. ebody = xmlvalue.getElementsByTagName("Body")
  236. if len(ebody) == 0:
  237. log(self, "Did not find <Body> for ExtensionObject", LOG_LEVEL_ERROR)
  238. return None
  239. ebody = ebody[0]
  240. # Body must contain an Object of type 'DataType' as defined in Variable
  241. ebodypart = ebody.firstChild
  242. if not ebodypart.nodeType == ebodypart.ELEMENT_NODE:
  243. ebodypart = getNextElementNode(ebodypart)
  244. if ebodypart == None:
  245. log(self, "Expected ExtensionObject to hold a variable of type " + str(self.parent.dataType().target().browseName()) + " but found nothing.", LOG_LEVEL_ERROR)
  246. return None
  247. if not ebodypart.tagName == self.parent.dataType().target().browseName():
  248. log(self, "Expected ExtensionObject to hold a variable of type " + str(self.parent.dataType().target().browseName()) + " but found " + str(ebodypart.tagName) + " instead.", LOG_LEVEL_ERROR)
  249. return None
  250. extobj.alias(ebodypart.tagName)
  251. ebodypart = ebodypart.firstChild
  252. if not ebodypart.nodeType == ebodypart.ELEMENT_NODE:
  253. ebodypart = getNextElementNode(ebodypart)
  254. if ebodypart == None:
  255. log(self, "Description of dataType " + str(self.parent.dataType().target().browseName()) + " in ExtensionObject is empty/invalid.", LOG_LEVEL_ERROR)
  256. return None
  257. extobj.value = []
  258. for e in enc:
  259. if not ebodypart == None:
  260. extobj.value.append(extobj.__parseXMLSingleValue(ebodypart, alias=None, encodingPart=e))
  261. else:
  262. log(self, "Expected encoding " + str(e) + " but found none in body.", LOG_LEVEL_ERROR)
  263. ebodypart = getNextElementNode(ebodypart)
  264. return extobj
  265. def setStringReprentation(self):
  266. pass
  267. def setNumericRepresentation(self):
  268. pass
  269. def getNumericRepresentation(self):
  270. return self.__binTypeId__
  271. def __str__(self):
  272. if self.__alias__ != None:
  273. return "'" + self.alias() + "':" + self.stringRepresentation + "(" + str(self.value) + ")"
  274. return self.stringRepresentation + "(" + str(self.value) + ")"
  275. def __repr__(self):
  276. return self.__str__()
  277. def printOpen62541CCode_SubType(self, asIndirect=True):
  278. return ""
  279. def printOpen62541CCode(self, bootstrapping = True):
  280. codegen = open62541_MacroHelper()
  281. code = []
  282. valueName = self.parent.getCodePrintableID() + "_variant_DataContents"
  283. # self.value either contains a list of multiple identical BUILTINTYPES, or it
  284. # contains a single builtintype (which may be a container); choose if we need
  285. # to create an array or a single variable.
  286. # Note that some genious defined that there are arrays of size 1, which are
  287. # distinctly different then a single value, so we need to check that as well
  288. # Semantics:
  289. # -3: Scalar or 1-dim
  290. # -2: Scalar or x-dim | x>0
  291. # -1: Scalar
  292. # 0: x-dim | x>0
  293. # n: n-dim | n>0
  294. if (len(self.value) == 0):
  295. return code
  296. if not isinstance(self.value[0], opcua_value_t):
  297. return code
  298. if self.parent.valueRank() != -1 and (self.parent.valueRank() >=0 or (len(self.value) > 1 and (self.parent.valueRank() != -2 or self.parent.valueRank() != -3))):
  299. # User the following strategy for all directly mappable values a la 'UA_Type MyInt = (UA_Type) 23;'
  300. if self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_GUID:
  301. log(self, "Don't know how to print array of GUID in node " + str(self.parent.id()), LOG_LEVEL_WARN)
  302. elif self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_DATETIME:
  303. log(self, "Don't know how to print array of DateTime in node " + str(self.parent.id()), LOG_LEVEL_WARN)
  304. elif self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_DIAGNOSTICINFO:
  305. log(self, "Don't know how to print array of DiagnosticInfo in node " + str(self.parent.id()), LOG_LEVEL_WARN)
  306. elif self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_STATUSCODE:
  307. log(self, "Don't know how to print array of StatusCode in node " + str(self.parent.id()), LOG_LEVEL_WARN)
  308. else:
  309. if self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_EXTENSIONOBJECT:
  310. for v in self.value:
  311. log(self, "Building extObj array index " + str(self.value.index(v)))
  312. code = code + v.printOpen62541CCode_SubType_build(arrayIndex=self.value.index(v))
  313. code.append("UA_Variant *" + self.parent.getCodePrintableID() + "_variant = UA_Variant_new();")
  314. code.append(self.parent.getCodePrintableID() + "_variant->type = &UA_TYPES[UA_TYPES_" + self.value[0].stringRepresentation.upper() + "];")
  315. code.append("UA_" + self.value[0].stringRepresentation + " " + valueName + "[" + str(len(self.value)) + "];")
  316. if self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_EXTENSIONOBJECT:
  317. for v in self.value:
  318. log(self, "Printing extObj array index " + str(self.value.index(v)))
  319. code.append(valueName + "[" + str(self.value.index(v)) + "] = " + v.printOpen62541CCode_SubType(asIndirect=False) + ";")
  320. code.append("UA_free(" + v.printOpen62541CCode_SubType() + ");")
  321. else:
  322. for v in self.value:
  323. code.append(valueName + "[" + str(self.value.index(v)) + "] = " + v.printOpen62541CCode_SubType() + ";")
  324. code.append("UA_Variant_setArrayCopy(" + self.parent.getCodePrintableID() + "_variant, &" + valueName + ", (UA_Int32) " + str(len(self.value)) + ", &UA_TYPES[UA_TYPES_" + self.value[0].stringRepresentation.upper() + "]);")
  325. # Variant creation is now part of printSubtypeEarly, the node does not exist when the type is initialized!
  326. #if (bootstrapping == True):
  327. # code.append(self.parent.getCodePrintableID() + "->value.variant = *" + self.parent.getCodePrintableID() + "_variant;")
  328. else:
  329. # User the following strategy for all directly mappable values a la 'UA_Type MyInt = (UA_Type) 23;'
  330. if self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_GUID:
  331. log(self, "Don't know how to print scalar GUID in node " + str(self.parent.id()), LOG_LEVEL_WARN)
  332. elif self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_DATETIME:
  333. log(self, "Don't know how to print scalar DateTime in node " + str(self.parent.id()), LOG_LEVEL_WARN)
  334. elif self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_DIAGNOSTICINFO:
  335. log(self, "Don't know how to print scalar DiagnosticInfo in node " + str(self.parent.id()), LOG_LEVEL_WARN)
  336. elif self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_STATUSCODE:
  337. log(self, "Don't know how to print scalar StatusCode in node " + str(self.parent.id()), LOG_LEVEL_WARN)
  338. else:
  339. # The following strategy applies to all other types, in particular strings and numerics.
  340. if self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_EXTENSIONOBJECT:
  341. code = code + self.value[0].printOpen62541CCode_SubType_build()
  342. code.append("UA_Variant *" + self.parent.getCodePrintableID() + "_variant = UA_Variant_new();")
  343. code.append(self.parent.getCodePrintableID() + "_variant->type = &UA_TYPES[UA_TYPES_" + self.value[0].stringRepresentation.upper() + "];")
  344. if self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_EXTENSIONOBJECT:
  345. code.append("UA_" + self.value[0].stringRepresentation + " *" + valueName + " = " + self.value[0].printOpen62541CCode_SubType() + ";")
  346. code.append("UA_Variant_setScalarCopy(" + self.parent.getCodePrintableID() + "_variant, " + valueName + ", &UA_TYPES[UA_TYPES_" + self.value[0].stringRepresentation.upper() + "]);")
  347. #FIXME: There is no membership definition for extensionObjects generated in this function.
  348. code.append("UA_" + self.value[0].stringRepresentation + "_deleteMembers(" + valueName + ");")
  349. # Variant creation is now part of printSubtypeEarly, the node does not exist when the type is initialized!
  350. #if (bootstrapping == True):
  351. # code.append(self.parent.getCodePrintableID() + "->value.variant = *" + self.parent.getCodePrintableID() + "_variant;")
  352. else:
  353. code.append("UA_" + self.value[0].stringRepresentation + " " + valueName + " = " + self.value[0].printOpen62541CCode_SubType() + ";")
  354. code.append("UA_Variant_setScalarCopy(" + self.parent.getCodePrintableID() + "_variant, &" + valueName + ", &UA_TYPES[UA_TYPES_" + self.value[0].stringRepresentation.upper() + "]);")
  355. code.append("UA_" + self.value[0].stringRepresentation + "_deleteMembers(&" + valueName + ");")
  356. # Variant creation is now part of printSubtypeEarly, the node does not exist when the type is initialized!
  357. #if (bootstrapping == True):
  358. # code.append(self.parent.getCodePrintableID() + "->value.variant = *" + self.parent.getCodePrintableID() + "_variant;")
  359. return code
  360. ###
  361. ### Actual buitlin types
  362. ###
  363. class opcua_BuiltinType_extensionObject_t(opcua_value_t):
  364. def setStringReprentation(self):
  365. self.stringRepresentation = "ExtensionObject"
  366. self.__typeId__ = None
  367. def setNumericRepresentation(self):
  368. self.__binTypeId__ = BUILTINTYPE_TYPEID_EXTENSIONOBJECT
  369. def typeId(self, data=None):
  370. if not data == None:
  371. self.__typeId__ = data
  372. return self.__typeId__
  373. def getCodeInstanceName(self):
  374. return self.__codeInstanceName__
  375. def setCodeInstanceName(self, recursionDepth, arrayIndex):
  376. self.__inVariableRecursionDepth__ = recursionDepth
  377. self.__inVariableArrayIndex__ = arrayIndex
  378. self.__codeInstanceName__ = self.parent.getCodePrintableID() + "_" + str(self.alias()) + "_" + str(arrayIndex) + "_" + str(recursionDepth)
  379. return self.__codeInstanceName__
  380. def printOpen62541CCode_SubType_build(self, recursionDepth=0, arrayIndex=0):
  381. code = [""]
  382. codegen = open62541_MacroHelper();
  383. log(self, "Building extensionObject for " + str(self.parent.id()))
  384. log(self, "Value " + str(self.value))
  385. log(self, "Encoding " + str(self.getEncodingRule()))
  386. self.setCodeInstanceName(recursionDepth, arrayIndex)
  387. # If there are any ExtensionObjects instide this ExtensionObject, we need to
  388. # generate one-time-structs for them too before we can proceed;
  389. for subv in self.value:
  390. if isinstance(subv, list):
  391. log(self, "ExtensionObject contains an ExtensionObject, which is currently not encodable!", LOG_LEVEL_ERR)
  392. code.append("struct {")
  393. for field in self.getEncodingRule():
  394. ptrSym = ""
  395. # If this is an Array, this is pointer to its contents with a AliasOfFieldSize entry
  396. if field[2] != 0:
  397. code.append(" UA_Int32 " + str(field[0]) + "Size;")
  398. ptrSym = "*"
  399. if len(field[1]) == 1:
  400. code.append(" UA_" + str(field[1][0]) + " " + ptrSym + str(field[0]) + ";")
  401. else:
  402. code.append(" UA_ExtensionObject " + " " + ptrSym + str(field[0]) + ";")
  403. code.append("} " + self.getCodeInstanceName() + "_struct;")
  404. # Assign data to the struct contents
  405. # Track the encoding rule definition to detect arrays and/or ExtensionObjects
  406. encFieldIdx = 0
  407. for subv in self.value:
  408. encField = self.getEncodingRule()[encFieldIdx]
  409. encFieldIdx = encFieldIdx + 1;
  410. log(self, "Encoding of field " + subv.alias() + " is " + str(subv.getEncodingRule()) + "defined by " + str(encField))
  411. # Check if this is an array
  412. if encField[2] == 0:
  413. code.append(self.getCodeInstanceName()+"_struct."+subv.alias() + " = " + subv.printOpen62541CCode_SubType(asIndirect=False) + ";")
  414. else:
  415. if isinstance(subv, list):
  416. # this is an array
  417. code.append(self.getCodeInstanceName()+"_struct."+subv.alias() + "Size = " + str(len(subv)) + ";")
  418. code.append(self.getCodeInstanceName()+"_struct."+subv.alias()+" = (UA_" + subv.stringRepresentation + " *) UA_malloc(sizeof(UA_" + subv.stringRepresentation + ")*"+ str(len(subv))+");")
  419. log(self, "Encoding included array of " + str(len(subv)) + " values.")
  420. for subvidx in range(0,len(subv)):
  421. subvv = subv[subvidx]
  422. log(self, " " + str(subvix) + " " + str(subvv))
  423. code.append(self.getCodeInstanceName()+"_struct."+subv.alias() + "[" + str(subvidx) + "] = " + subvv.printOpen62541CCode_SubType(asIndirect=True) + ";")
  424. code.append("}")
  425. else:
  426. code.append(self.getCodeInstanceName()+"_struct."+subv.alias() + "Size = 1;")
  427. code.append(self.getCodeInstanceName()+"_struct."+subv.alias()+" = (UA_" + subv.stringRepresentation + " *) UA_malloc(sizeof(UA_" + subv.stringRepresentation + "));")
  428. code.append(self.getCodeInstanceName()+"_struct."+subv.alias() + "[0] = " + subv.printOpen62541CCode_SubType(asIndirect=True) + ";")
  429. # Allocate some memory
  430. code.append("UA_ExtensionObject *" + self.getCodeInstanceName() + " = UA_ExtensionObject_new();")
  431. code.append(self.getCodeInstanceName() + "->encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;")
  432. code.append(self.getCodeInstanceName() + "->typeId = UA_NODEID_NUMERIC(" + str(self.parent.dataType().target().id().ns) + ", " + str(self.parent.dataType().target().id().i) + "+ UA_ENCODINGOFFSET_BINARY);")
  433. code.append("UA_ByteString_newMembers(&" + self.getCodeInstanceName() + "->body, 65000);" )
  434. # Encode each value as a bytestring seperately.
  435. code.append("size_t " + self.getCodeInstanceName() + "_encOffset = 0;" )
  436. encFieldIdx = 0;
  437. for subv in self.value:
  438. encField = self.getEncodingRule()[encFieldIdx]
  439. encFieldIdx = encFieldIdx + 1;
  440. if encField[2] == 0:
  441. code.append("UA_" + subv.stringRepresentation + "_encodeBinary(&" + self.getCodeInstanceName()+"_struct."+subv.alias() + ", &" + self.getCodeInstanceName() + "->body, &" + self.getCodeInstanceName() + "_encOffset);" )
  442. else:
  443. if isinstance(subv, list):
  444. for subvidx in range(0,len(subv)):
  445. code.append("UA_" + subv.stringRepresentation + "_encodeBinary(&" + self.getCodeInstanceName()+"_struct."+subv.alias() + "[" + str(subvidx) + "], &" + self.getCodeInstanceName() + "->body, &" + self.getCodeInstanceName() + "_encOffset);" )
  446. else:
  447. code.append("UA_" + subv.stringRepresentation + "_encodeBinary(&" + self.getCodeInstanceName()+"_struct."+subv.alias() + "[0], &" + self.getCodeInstanceName() + "->body, &" + self.getCodeInstanceName() + "_encOffset);" )
  448. # Reallocate the memory by swapping the 65k Bytestring for a new one
  449. code.append(self.getCodeInstanceName() + "->body.length = " + self.getCodeInstanceName() + "_encOffset;");
  450. code.append("UA_Byte *" + self.getCodeInstanceName() + "_newBody = (UA_Byte *) UA_malloc(" + self.getCodeInstanceName() + "_encOffset );" )
  451. code.append("memcpy(" + self.getCodeInstanceName() + "_newBody, " + self.getCodeInstanceName() + "->body.data, " + self.getCodeInstanceName() + "_encOffset);" )
  452. code.append("UA_Byte *" + self.getCodeInstanceName() + "_oldBody = " + self.getCodeInstanceName() + "->body.data;");
  453. code.append(self.getCodeInstanceName() + "->body.data = " +self.getCodeInstanceName() + "_newBody;")
  454. code.append("UA_free(" + self.getCodeInstanceName() + "_oldBody);")
  455. code.append("")
  456. return code
  457. def printOpen62541CCode_SubType(self, asIndirect=True):
  458. if asIndirect == False:
  459. return "*" + str(self.getCodeInstanceName())
  460. return str(self.getCodeInstanceName())
  461. def __str__(self):
  462. return "'" + self.alias() + "':" + self.stringRepresentation + "(" + str(self.value) + ")"
  463. class opcua_BuiltinType_localizedtext_t(opcua_value_t):
  464. def setStringReprentation(self):
  465. self.stringRepresentation = "LocalizedText"
  466. def setNumericRepresentation(self):
  467. self.__binTypeId__ = BUILTINTYPE_TYPEID_LOCALIZEDTEXT
  468. def parseXML(self, xmlvalue):
  469. # Expect <LocalizedText> or <AliasName>
  470. # <Locale>xx_XX</Locale>
  471. # <Text>TextText</Text>
  472. # <LocalizedText> or </AliasName>
  473. #
  474. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  475. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  476. return
  477. if self.alias() != None:
  478. if not self.alias() == xmlvalue.tagName:
  479. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  480. else:
  481. if not self.stringRepresentation == xmlvalue.tagName:
  482. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  483. if xmlvalue.firstChild == None:
  484. if self.alias() != None:
  485. log(self, "Neither locale nor text in XML description field " + self.alias() + ". Setting to default ['en_US','']")
  486. else:
  487. log(self, "Neither locale nor text in XML description. Setting to default ['en_US','']")
  488. self.value = ['en_US','']
  489. return
  490. self.value = []
  491. tmp = xmlvalue.getElementsByTagName("Locale")
  492. if len(tmp) == 0:
  493. log(self, "Did not find a locale. Setting to en_US per default.", LOG_LEVEL_WARN)
  494. self.value.append('en_US')
  495. else:
  496. if tmp[0].firstChild == None:
  497. log(self, "Locale tag without contents. Setting to en_US per default.", LOG_LEVEL_WARN)
  498. self.value.append('en_US')
  499. else:
  500. self.value.append(tmp[0].firstChild.data)
  501. clean = ""
  502. for s in self.value[0]:
  503. if s in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_":
  504. clean = clean + s
  505. self.value[0] = clean
  506. tmp = xmlvalue.getElementsByTagName("Text")
  507. if len(tmp) == 0:
  508. log(self, "Did not find a Text. Setting to empty string per default.", LOG_LEVEL_WARN)
  509. self.value.append('')
  510. else:
  511. if tmp[0].firstChild == None:
  512. log(self, "Text tag without content. Setting to empty string per default.", LOG_LEVEL_WARN)
  513. self.value.append('')
  514. else:
  515. self.value.append(tmp[0].firstChild.data)
  516. def printOpen62541CCode_SubType(self, asIndirect=True):
  517. if asIndirect==True:
  518. code = "UA_LOCALIZEDTEXT_ALLOC(\"" + str(self.value[0]) + "\", \"" + str(self.value[1].encode('utf-8')) + "\")"
  519. else:
  520. code = "UA_LOCALIZEDTEXT(\"" + str(self.value[0]) + "\", \"" + str(self.value[1].encode('utf-8')) + "\")"
  521. return code
  522. class opcua_BuiltinType_expandednodeid_t(opcua_value_t):
  523. def setStringReprentation(self):
  524. self.stringRepresentation = "ExpandedNodeId"
  525. def setNumericRepresentation(self):
  526. self.__binTypeId__ = BUILTINTYPE_TYPEID_EXPANDEDNODEID
  527. def parseXML(self, xmlvalue):
  528. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  529. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  530. return
  531. log(self, "Not implemented", LOG_LEVEL_ERR)
  532. def printOpen62541CCode_SubType(self, asIndirect=True):
  533. #FIXME! This one is definetely broken!
  534. code = ""
  535. return code
  536. class opcua_BuiltinType_nodeid_t(opcua_value_t):
  537. def setStringReprentation(self):
  538. self.stringRepresentation = "NodeId"
  539. def setNumericRepresentation(self):
  540. self.__binTypeId__ = BUILTINTYPE_TYPEID_NODEID
  541. def parseXML(self, xmlvalue):
  542. # Expect <NodeId> or <Alias>
  543. # <Identifier> # It is unclear whether or not this is manditory. Identifier tags are used in Namespace 0.
  544. # ns=x;i=y or similar string representation of id()
  545. # </Identifier>
  546. # </NodeId> or </Alias>
  547. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  548. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  549. return
  550. if self.alias() != None:
  551. if not self.alias() == xmlvalue.tagName:
  552. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  553. else:
  554. if not self.stringRepresentation == xmlvalue.tagName:
  555. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  556. # Catch XML <NodeId />
  557. if xmlvalue.firstChild == None :
  558. log(self, "No value is given, which is illegal for Node Types...", LOG_LEVEL_ERROR)
  559. self.value = None
  560. else:
  561. # Check if there is an <Identifier> tag
  562. if len(xmlvalue.getElementsByTagName("Identifier")) != 0:
  563. xmlvalue = xmlvalue.getElementsByTagName("Identifier")[0]
  564. self.value = self.parent.getNamespace().getNodeByIDString(unicode(xmlvalue.firstChild.data))
  565. if self.value == None:
  566. log(self, "Node with id " + str(unicode(xmlvalue.firstChild.data)) + " was not found in namespace.", LOG_LEVEL_ERROR)
  567. def printOpen62541CCode_SubType(self, asIndirect=True):
  568. if self.value == None:
  569. return "UA_NODEID_NUMERIC(0,0)"
  570. nodeId = self.value.id()
  571. if nodeId.i != None:
  572. return "UA_NODEID_NUMERIC(" + str(nodeId.ns) + ", " + str(nodeId.i) + ")"
  573. elif nodeId.s != None:
  574. return "UA_NODEID_STRING(" + str(nodeId.ns) + ", " + str(nodeId.s) + ")"
  575. elif nodeId.b != None:
  576. log(self, "NodeID Generation macro for bytestrings has not been implemented.")
  577. return "UA_NODEID_NUMERIC(0,0)"
  578. elif nodeId.g != None:
  579. log(self, "NodeID Generation macro for guids has not been implemented.")
  580. return "UA_NODEID_NUMERIC(0,0)"
  581. return "UA_NODEID_NUMERIC(0,0)"
  582. class opcua_BuiltinType_datetime_t(opcua_value_t):
  583. def setStringReprentation(self):
  584. self.stringRepresentation = "DateTime"
  585. def setNumericRepresentation(self):
  586. self.__binTypeId__ = BUILTINTYPE_TYPEID_DATETIME
  587. def parseXML(self, xmlvalue):
  588. # Expect <DateTime> or <AliasName>
  589. # 2013-08-13T21:00:05.0000L
  590. # </DateTime> or </AliasName>
  591. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  592. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  593. return
  594. if self.alias() != None:
  595. if not self.alias() == xmlvalue.tagName:
  596. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  597. else:
  598. if not self.stringRepresentation == xmlvalue.tagName:
  599. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  600. # Catch XML <DateTime /> by setting the value to a default
  601. if xmlvalue.firstChild == None :
  602. log(self, "No value is given. Setting to default now()")
  603. self.value = strptime(strftime("%Y-%m-%dT%H:%M%S"), "%Y-%m-%dT%H:%M%S")
  604. else:
  605. timestr = unicode(xmlvalue.firstChild.data)
  606. # .NET tends to create this garbage %Y-%m-%dT%H:%M:%S.0000z
  607. # strip everything after the "." away for a posix time_struct
  608. if "." in timestr:
  609. timestr = timestr[:timestr.index(".")]
  610. # If the last character is not numeric, remove it
  611. while len(timestr)>0 and not timestr[-1] in "0123456789":
  612. timestr = timestr[:-1]
  613. try:
  614. self.value = strptime(timestr, "%Y-%m-%dT%H:%M:%S")
  615. except:
  616. log(self, "Timestring format is illegible. Expected 2001-01-30T21:22:23, but got " + timestr + " instead. Time will be defaultet to now()", LOG_LEVEL_ERROR)
  617. self.value = strptime(strftime("%Y-%m-%dT%H:%M%S"), "%Y-%m-%dT%H:%M%S")
  618. class opcua_BuiltinType_qualifiedname_t(opcua_value_t):
  619. def setStringReprentation(self):
  620. self.stringRepresentation = "QualifiedName"
  621. def setNumericRepresentation(self):
  622. self.__binTypeId__ = BUILTINTYPE_TYPEID_QUALIFIEDNAME
  623. def parseXML(self, xmlvalue):
  624. # Expect <QualifiedName> or <AliasName>
  625. # <NamespaceIndex>Int16<NamespaceIndex> # Optional, apparently ommitted if ns=0 ??? (Not given in OPCUA Nodeset2)
  626. # <Name>SomeString<Name> # Speculation: Manditory if NamespaceIndex is given, omitted otherwise?
  627. # </QualifiedName> or </AliasName>
  628. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  629. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  630. return
  631. if self.alias() != None:
  632. if not self.alias() == xmlvalue.tagName:
  633. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  634. else:
  635. if not self.stringRepresentation == xmlvalue.tagName:
  636. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  637. # Catch XML <Qalified /> by setting the value to a default
  638. if xmlvalue.firstChild == None :
  639. log(self, "No value is given. Setting to default empty string in ns=0: [0, '']")
  640. self.value = [0, '']
  641. else:
  642. # Is a namespace index passed?
  643. if len(xmlvalue.getElementsByTagName("NamespaceIndex")) != 0:
  644. self.value = [int(xmlvalue.getElementsByTagName("NamespaceIndex")[0].firstChild.data)]
  645. # namespace index is passed and <Name> tags are now manditory?
  646. if len(xmlvalue.getElementsByTagName("Name")) != 0:
  647. self.value.append(xmlvalue.getElementsByTagName("Name")[0].firstChild.data)
  648. else:
  649. log(self, "No name is specified, will default to empty string")
  650. self.value.append('')
  651. else:
  652. log(self, "No namespace is specified, will default to 0")
  653. self.value = [0]
  654. self.value.append(unicode(xmlvalue.firstChild.data))
  655. def printOpen62541CCode_SubType(self, asIndirect=True):
  656. code = "UA_QUALIFIEDNAME_ALLOC(" + str(self.value[0]) + ", \"" + self.value[1].encode('utf-8') + "\")"
  657. return code
  658. class opcua_BuiltinType_statuscode_t(opcua_value_t):
  659. def setStringReprentation(self):
  660. self.stringRepresentation = "StatusCode"
  661. def setNumericRepresentation(self):
  662. self.__binTypeId__ = BUILTINTYPE_TYPEID_STATUSCODE
  663. def parseXML(self, xmlvalue):
  664. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  665. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  666. return
  667. log(self, "Not implemented", LOG_LEVEL_WARN)
  668. class opcua_BuiltinType_diagnosticinfo_t(opcua_value_t):
  669. def setStringReprentation(self):
  670. self.stringRepresentation = "StatusCode"
  671. def setNumericRepresentation(self):
  672. self.__binTypeId__ = BUILTINTYPE_TYPEID_DIAGNOSTICINFO
  673. def parseXML(self, xmlvalue):
  674. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  675. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  676. return
  677. log(self, "Not implemented", LOG_LEVEL_WARN)
  678. class opcua_BuiltinType_guid_t(opcua_value_t):
  679. def setStringReprentation(self):
  680. self.stringRepresentation = "Guid"
  681. def setNumericRepresentation(self):
  682. self.__binTypeId__ = BUILTINTYPE_TYPEID_GUID
  683. def parseXML(self, xmlvalue):
  684. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  685. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  686. return
  687. if self.alias() != None:
  688. if not self.alias() == xmlvalue.tagName:
  689. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  690. else:
  691. if not self.stringRepresentation == xmlvalue.tagName:
  692. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  693. # Catch XML <Guid /> by setting the value to a default
  694. if xmlvalue.firstChild == None:
  695. log(self, "No value is given. Setting to default 0")
  696. self.value = [0,0,0,0]
  697. else:
  698. self.value = unicode(xmlvalue.firstChild.data)
  699. self.value = self.value.replace("{","")
  700. self.value = self.value.replace("}","")
  701. self.value = self.value.split("-")
  702. tmp = []
  703. ok = True
  704. for g in self.value:
  705. try:
  706. tmp.append(int("0x"+g, 16))
  707. except:
  708. log(self, "Invalid formatting of Guid. Expected {01234567-89AB-CDEF-ABCD-0123456789AB}, got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  709. self.value = [0,0,0,0,0]
  710. ok = False
  711. if len(tmp) != 5:
  712. log(self, "Invalid formatting of Guid. Expected {01234567-89AB-CDEF-ABCD-0123456789AB}, got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  713. self.value = [0,0,0,0]
  714. ok = False
  715. self.value = tmp
  716. class opcua_BuiltinType_boolean_t(opcua_value_t):
  717. def setStringReprentation(self):
  718. self.stringRepresentation = "Boolean"
  719. def setNumericRepresentation(self):
  720. self.__binTypeId__ = BUILTINTYPE_TYPEID_BOOLEAN
  721. def parseXML(self, xmlvalue):
  722. # Expect <Boolean>value</Boolean> or
  723. # <Aliasname>value</Aliasname>
  724. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  725. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  726. return
  727. if self.alias() != None:
  728. if not self.alias() == xmlvalue.tagName:
  729. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  730. else:
  731. if not self.stringRepresentation == xmlvalue.tagName:
  732. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  733. # Catch XML <Boolean /> by setting the value to a default
  734. if xmlvalue.firstChild == None:
  735. log(self, "No value is given. Setting to default 0")
  736. self.value = False
  737. else:
  738. if "false" in unicode(xmlvalue.firstChild.data).lower():
  739. self.value = False
  740. else:
  741. self.value = True
  742. def printOpen62541CCode_SubType(self, asIndirect=True):
  743. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  744. class opcua_BuiltinType_byte_t(opcua_value_t):
  745. def setStringReprentation(self):
  746. self.stringRepresentation = "Byte"
  747. def setNumericRepresentation(self):
  748. self.__binTypeId__ = BUILTINTYPE_TYPEID_BYTE
  749. def parseXML(self, xmlvalue):
  750. # Expect <Byte>value</Byte> or
  751. # <Aliasname>value</Aliasname>
  752. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  753. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  754. return
  755. if self.alias() != None:
  756. if not self.alias() == xmlvalue.tagName:
  757. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  758. else:
  759. if not self.stringRepresentation == xmlvalue.tagName:
  760. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  761. # Catch XML <Byte /> by setting the value to a default
  762. if xmlvalue.firstChild == None:
  763. log(self, "No value is given. Setting to default 0")
  764. self.value = 0
  765. else:
  766. try:
  767. self.value = int(unicode(xmlvalue.firstChild.data))
  768. except:
  769. log(self, "Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  770. def printOpen62541CCode_SubType(self, asIndirect=True):
  771. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  772. class opcua_BuiltinType_sbyte_t(opcua_value_t):
  773. def setStringReprentation(self):
  774. self.stringRepresentation = "SByte"
  775. def setNumericRepresentation(self):
  776. self.__binTypeId__ = BUILTINTYPE_TYPEID_SBYTE
  777. def parseXML(self, xmlvalue):
  778. # Expect <SByte>value</SByte> or
  779. # <Aliasname>value</Aliasname>
  780. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  781. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  782. return
  783. if self.alias() != None:
  784. if not self.alias() == xmlvalue.tagName:
  785. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  786. else:
  787. if not self.stringRepresentation == xmlvalue.tagName:
  788. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  789. # Catch XML <SByte /> by setting the value to a default
  790. if xmlvalue.firstChild == None:
  791. log(self, "No value is given. Setting to default 0")
  792. self.value = 0
  793. else:
  794. try:
  795. self.value = int(unicode(xmlvalue.firstChild.data))
  796. except:
  797. log(self, "Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  798. def printOpen62541CCode_SubType(self, asIndirect=True):
  799. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  800. class opcua_BuiltinType_int16_t(opcua_value_t):
  801. def setStringReprentation(self):
  802. self.stringRepresentation = "Int16"
  803. def setNumericRepresentation(self):
  804. self.__binTypeId__ = BUILTINTYPE_TYPEID_INT16
  805. def parseXML(self, xmlvalue):
  806. # Expect <Int16>value</Int16> or
  807. # <Aliasname>value</Aliasname>
  808. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  809. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  810. return
  811. if self.alias() != None:
  812. if not self.alias() == xmlvalue.tagName:
  813. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  814. else:
  815. if not self.stringRepresentation == xmlvalue.tagName:
  816. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  817. # Catch XML <Int16 /> by setting the value to a default
  818. if xmlvalue.firstChild == None:
  819. log(self, "No value is given. Setting to default 0")
  820. self.value = 0
  821. else:
  822. try:
  823. self.value = int(unicode(xmlvalue.firstChild.data))
  824. except:
  825. log(self, "Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  826. def printOpen62541CCode_SubType(self, asIndirect=True):
  827. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  828. class opcua_BuiltinType_uint16_t(opcua_value_t):
  829. def setStringReprentation(self):
  830. self.stringRepresentation = "UInt16"
  831. def setNumericRepresentation(self):
  832. self.__binTypeId__ = BUILTINTYPE_TYPEID_UINT16
  833. def parseXML(self, xmlvalue):
  834. # Expect <UInt16>value</UInt16> or
  835. # <Aliasname>value</Aliasname>
  836. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  837. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  838. return
  839. if self.alias() != None:
  840. if not self.alias() == xmlvalue.tagName:
  841. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  842. else:
  843. if not self.stringRepresentation == xmlvalue.tagName:
  844. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  845. # Catch XML <UInt16 /> by setting the value to a default
  846. if xmlvalue.firstChild == None:
  847. log(self, "No value is given. Setting to default 0")
  848. self.value = 0
  849. else:
  850. try:
  851. self.value = int(unicode(xmlvalue.firstChild.data))
  852. except:
  853. log(self, "Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  854. def printOpen62541CCode_SubType(self, asIndirect=True):
  855. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  856. class opcua_BuiltinType_int32_t(opcua_value_t):
  857. def setStringReprentation(self):
  858. self.stringRepresentation = "Int32"
  859. def setNumericRepresentation(self):
  860. self.__binTypeId__ = BUILTINTYPE_TYPEID_INT32
  861. def parseXML(self, xmlvalue):
  862. # Expect <Int32>value</Int32> or
  863. # <Aliasname>value</Aliasname>
  864. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  865. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  866. return
  867. if self.alias() != None:
  868. if not self.alias() == xmlvalue.tagName:
  869. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  870. else:
  871. if not self.stringRepresentation == xmlvalue.tagName:
  872. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  873. # Catch XML <Int32 /> by setting the value to a default
  874. if xmlvalue.firstChild == None:
  875. log(self, "No value is given. Setting to default 0")
  876. self.value = 0
  877. else:
  878. try:
  879. self.value = int(unicode(xmlvalue.firstChild.data))
  880. except:
  881. log(self, "Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  882. def printOpen62541CCode_SubType(self, asIndirect=True):
  883. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  884. class opcua_BuiltinType_uint32_t(opcua_value_t):
  885. def setStringReprentation(self):
  886. self.stringRepresentation = "UInt32"
  887. def setNumericRepresentation(self):
  888. self.__binTypeId__ = BUILTINTYPE_TYPEID_UINT32
  889. def parseXML(self, xmlvalue):
  890. # Expect <UInt32>value</UInt32> or
  891. # <Aliasname>value</Aliasname>
  892. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  893. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  894. return
  895. if self.alias() != None:
  896. if not self.alias() == xmlvalue.tagName:
  897. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  898. else:
  899. if not self.stringRepresentation == xmlvalue.tagName:
  900. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  901. # Catch XML <UInt32 /> by setting the value to a default
  902. if xmlvalue.firstChild == None:
  903. log(self, "No value is given. Setting to default 0")
  904. self.value = 0
  905. else:
  906. try:
  907. self.value = int(unicode(xmlvalue.firstChild.data))
  908. except:
  909. log(self, "Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  910. def printOpen62541CCode_SubType(self, asIndirect=True):
  911. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  912. class opcua_BuiltinType_int64_t(opcua_value_t):
  913. def setStringReprentation(self):
  914. self.stringRepresentation = "Int64"
  915. def setNumericRepresentation(self):
  916. self.__binTypeId__ = BUILTINTYPE_TYPEID_INT64
  917. def parseXML(self, xmlvalue):
  918. # Expect <Int64>value</Int64> or
  919. # <Aliasname>value</Aliasname>
  920. if self.alias() != None:
  921. if not self.alias() == xmlvalue.tagName:
  922. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  923. else:
  924. if not self.stringRepresentation == xmlvalue.tagName:
  925. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  926. # Catch XML <Int64 /> by setting the value to a default
  927. if xmlvalue.firstChild == None:
  928. log(self, "No value is given. Setting to default 0")
  929. self.value = 0
  930. else:
  931. try:
  932. self.value = int(unicode(xmlvalue.firstChild.data))
  933. except:
  934. log(self, "Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  935. def printOpen62541CCode_SubType(self, asIndirect=True):
  936. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  937. class opcua_BuiltinType_uint64_t(opcua_value_t):
  938. def setStringReprentation(self):
  939. self.stringRepresentation = "UInt64"
  940. def setNumericRepresentation(self):
  941. self.__binTypeId__ = BUILTINTYPE_TYPEID_UINT64
  942. def parseXML(self, xmlvalue):
  943. # Expect <UInt16>value</UInt16> or
  944. # <Aliasname>value</Aliasname>
  945. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  946. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  947. return
  948. if self.alias() != None:
  949. if not self.alias() == xmlvalue.tagName:
  950. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  951. else:
  952. if not self.stringRepresentation == xmlvalue.tagName:
  953. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  954. # Catch XML <UInt64 /> by setting the value to a default
  955. if xmlvalue.firstChild == None:
  956. log(self, "No value is given. Setting to default 0")
  957. self.value = 0
  958. else:
  959. try:
  960. self.value = int(unicode(xmlvalue.firstChild.data))
  961. except:
  962. log(self, "Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  963. def printOpen62541CCode_SubType(self, asIndirect=True):
  964. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  965. class opcua_BuiltinType_float_t(opcua_value_t):
  966. def setStringReprentation(self):
  967. self.stringRepresentation = "Float"
  968. def setNumericRepresentation(self):
  969. self.__binTypeId__ = BUILTINTYPE_TYPEID_FLOAT
  970. def parseXML(self, xmlvalue):
  971. # Expect <Float>value</Float> or
  972. # <Aliasname>value</Aliasname>
  973. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  974. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  975. return
  976. if self.alias() != None:
  977. if not self.alias() == xmlvalue.tagName:
  978. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  979. else:
  980. if not self.stringRepresentation == xmlvalue.tagName:
  981. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  982. # Catch XML <Float /> by setting the value to a default
  983. if xmlvalue.firstChild == None:
  984. log(self, "No value is given. Setting to default 0")
  985. self.value = 0.0
  986. else:
  987. try:
  988. self.value = float(unicode(xmlvalue.firstChild.data))
  989. except:
  990. log(self, "Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  991. def printOpen62541CCode_SubType(self, asIndirect=True):
  992. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  993. class opcua_BuiltinType_double_t(opcua_value_t):
  994. def setStringReprentation(self):
  995. self.stringRepresentation = "Double"
  996. def setNumericRepresentation(self):
  997. self.__binTypeId__ = BUILTINTYPE_TYPEID_DOUBLE
  998. def parseXML(self, xmlvalue):
  999. # Expect <Double>value</Double> or
  1000. # <Aliasname>value</Aliasname>
  1001. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  1002. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  1003. return
  1004. if self.alias() != None:
  1005. if not self.alias() == xmlvalue.tagName:
  1006. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  1007. else:
  1008. if not self.stringRepresentation == xmlvalue.tagName:
  1009. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  1010. # Catch XML <Double /> by setting the value to a default
  1011. if xmlvalue.firstChild == None:
  1012. log(self, "No value is given. Setting to default 0")
  1013. self.value = 0.0
  1014. else:
  1015. try:
  1016. self.value = float(unicode(xmlvalue.firstChild.data))
  1017. except:
  1018. log(self, "Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data), LOG_LEVEL_ERROR)
  1019. def printOpen62541CCode_SubType(self, asIndirect=True):
  1020. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  1021. class opcua_BuiltinType_string_t(opcua_value_t):
  1022. def setStringReprentation(self):
  1023. self.stringRepresentation = "String"
  1024. def setNumericRepresentation(self):
  1025. self.__binTypeId__ = BUILTINTYPE_TYPEID_STRING
  1026. def pack(self):
  1027. bin = structpack("I", len(unicode(self.value)))
  1028. bin = bin + str(self.value)
  1029. return bin
  1030. def parseXML(self, xmlvalue):
  1031. # Expect <String>value</String> or
  1032. # <Aliasname>value</Aliasname>
  1033. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  1034. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  1035. return
  1036. if self.alias() != None:
  1037. if not self.alias() == xmlvalue.tagName:
  1038. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  1039. else:
  1040. if not self.stringRepresentation == xmlvalue.tagName:
  1041. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  1042. # Catch XML <String /> by setting the value to a default
  1043. if xmlvalue.firstChild == None:
  1044. log(self, "No value is given. Setting to default 0")
  1045. self.value = ""
  1046. else:
  1047. self.value = str(unicode(xmlvalue.firstChild.data))
  1048. def printOpen62541CCode_SubType(self, asIndirect=True):
  1049. code = "UA_STRING_ALLOC(\"" + self.value.encode('utf-8') + "\")"
  1050. return code
  1051. class opcua_BuiltinType_xmlelement_t(opcua_BuiltinType_string_t):
  1052. def setStringReprentation(self):
  1053. self.stringRepresentation = "XmlElement"
  1054. def setNumericRepresentation(self):
  1055. self.__binTypeId__ = BUILTINTYPE_TYPEID_XMLELEMENT
  1056. def printOpen62541CCode_SubType(self, asIndirect=True):
  1057. code = "UA_XMLELEMENT_ALLOC(\"" + self.value.encode('utf-8') + "\")"
  1058. return code
  1059. class opcua_BuiltinType_bytestring_t(opcua_value_t):
  1060. def setStringReprentation(self):
  1061. self.stringRepresentation = "ByteString"
  1062. def setNumericRepresentation(self):
  1063. self.__binTypeId__ = BUILTINTYPE_TYPEID_BYTESTRING
  1064. def parseXML(self, xmlvalue):
  1065. # Expect <ByteString>value</ByteString> or
  1066. # <Aliasname>value</Aliasname>
  1067. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  1068. log(self, "Expected XML Element, but got junk...", LOG_LEVEL_ERROR)
  1069. return
  1070. if self.alias() != None:
  1071. if not self.alias() == xmlvalue.tagName:
  1072. log(self, "Expected an aliased XML field called " + self.alias() + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  1073. else:
  1074. if not self.stringRepresentation == xmlvalue.tagName:
  1075. log(self, "Expected XML field " + self.stringRepresentation + " but got " + xmlvalue.tagName + " instead. This is a parsing error of opcua_value_t.__parseXMLSingleValue(), will try to continue anyway.", LOG_LEVEL_WARN)
  1076. # Catch XML <ByteString /> by setting the value to a default
  1077. if xmlvalue.firstChild == None:
  1078. log(self, "No value is given. Setting to default 0")
  1079. self.value = ""
  1080. else:
  1081. self.value = str(unicode(xmlvalue.firstChild.data))
  1082. def printOpen62541CCode_SubType(self, asIndirect=True):
  1083. bs = ""
  1084. for line in self.value:
  1085. bs = bs + str(line).replace("\n","");
  1086. outs = bs
  1087. log(self, "Encoded Bytestring: " + outs, LOG_LEVEL_DEBUG)
  1088. # bs = bs.decode('base64')
  1089. # outs = ""
  1090. # for s in bs:
  1091. # outs = outs + hex(ord(s)).upper().replace("0X", "\\x")
  1092. code = "UA_STRING_ALLOC(\"" + outs + "\")"
  1093. return code