ua_builtin_types.py 60 KB

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