ua_builtin_types.py 58 KB

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