ua_builtin_types.py 59 KB

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