ua_builtin_types.py 59 KB

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