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