ua_builtin_types.py 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  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. code.append("UA_" + self.value[0].stringRepresentation + " " + valueName + " = " + self.value[0].printOpen62541CCode_SubType() + ";")
  363. code.append("UA_Variant_setScalar( &attr.value, &" + valueName + ", &UA_TYPES[UA_TYPES_" + self.value[0].stringRepresentation.upper() + "]);")
  364. code.append("UA_" + self.value[0].stringRepresentation + "_deleteMembers(&" + valueName + ");")
  365. return code
  366. ###
  367. ### Actual buitlin types
  368. ###
  369. class opcua_BuiltinType_extensionObject_t(opcua_value_t):
  370. def setStringReprentation(self):
  371. self.stringRepresentation = "ExtensionObject"
  372. self.__typeId__ = None
  373. def setNumericRepresentation(self):
  374. self.__binTypeId__ = BUILTINTYPE_TYPEID_EXTENSIONOBJECT
  375. def typeId(self, data=None):
  376. if not data == None:
  377. self.__typeId__ = data
  378. return self.__typeId__
  379. def getCodeInstanceName(self):
  380. return self.__codeInstanceName__
  381. def setCodeInstanceName(self, recursionDepth, arrayIndex):
  382. self.__inVariableRecursionDepth__ = recursionDepth
  383. self.__inVariableArrayIndex__ = arrayIndex
  384. self.__codeInstanceName__ = self.parent.getCodePrintableID() + "_" + str(self.alias()) + "_" + str(arrayIndex) + "_" + str(recursionDepth)
  385. return self.__codeInstanceName__
  386. def printOpen62541CCode_SubType_build(self, recursionDepth=0, arrayIndex=0):
  387. code = [""]
  388. codegen = open62541_MacroHelper();
  389. logger.debug("Building extensionObject for " + str(self.parent.id()))
  390. logger.debug("Value " + str(self.value))
  391. logger.debug("Encoding " + str(self.getEncodingRule()))
  392. self.setCodeInstanceName(recursionDepth, arrayIndex)
  393. # If there are any ExtensionObjects instide this ExtensionObject, we need to
  394. # generate one-time-structs for them too before we can proceed;
  395. for subv in self.value:
  396. if isinstance(subv, list):
  397. logger.debug("ExtensionObject contains an ExtensionObject, which is currently not encodable!", LOG_LEVEL_ERR)
  398. code.append("struct {")
  399. for field in self.getEncodingRule():
  400. ptrSym = ""
  401. # If this is an Array, this is pointer to its contents with a AliasOfFieldSize entry
  402. if field[2] != 0:
  403. code.append(" UA_Int32 " + str(field[0]) + "Size;")
  404. ptrSym = "*"
  405. if len(field[1]) == 1:
  406. code.append(" UA_" + str(field[1][0]) + " " + ptrSym + str(field[0]) + ";")
  407. else:
  408. code.append(" UA_ExtensionObject " + " " + ptrSym + str(field[0]) + ";")
  409. code.append("} " + self.getCodeInstanceName() + "_struct;")
  410. # Assign data to the struct contents
  411. # Track the encoding rule definition to detect arrays and/or ExtensionObjects
  412. encFieldIdx = 0
  413. for subv in self.value:
  414. encField = self.getEncodingRule()[encFieldIdx]
  415. encFieldIdx = encFieldIdx + 1;
  416. logger.debug("Encoding of field " + subv.alias() + " is " + str(subv.getEncodingRule()) + "defined by " + str(encField))
  417. # Check if this is an array
  418. if encField[2] == 0:
  419. code.append(self.getCodeInstanceName()+"_struct."+subv.alias() + " = " + subv.printOpen62541CCode_SubType(asIndirect=False) + ";")
  420. else:
  421. if isinstance(subv, list):
  422. # this is an array
  423. code.append(self.getCodeInstanceName()+"_struct."+subv.alias() + "Size = " + str(len(subv)) + ";")
  424. code.append(self.getCodeInstanceName()+"_struct."+subv.alias()+" = (UA_" + subv.stringRepresentation + " *) UA_malloc(sizeof(UA_" + subv.stringRepresentation + ")*"+ str(len(subv))+");")
  425. logger.debug("Encoding included array of " + str(len(subv)) + " values.")
  426. for subvidx in range(0,len(subv)):
  427. subvv = subv[subvidx]
  428. logger.debug(" " + str(subvix) + " " + str(subvv))
  429. code.append(self.getCodeInstanceName()+"_struct."+subv.alias() + "[" + str(subvidx) + "] = " + subvv.printOpen62541CCode_SubType(asIndirect=True) + ";")
  430. code.append("}")
  431. else:
  432. code.append(self.getCodeInstanceName()+"_struct."+subv.alias() + "Size = 1;")
  433. code.append(self.getCodeInstanceName()+"_struct."+subv.alias()+" = (UA_" + subv.stringRepresentation + " *) UA_malloc(sizeof(UA_" + subv.stringRepresentation + "));")
  434. code.append(self.getCodeInstanceName()+"_struct."+subv.alias() + "[0] = " + subv.printOpen62541CCode_SubType(asIndirect=True) + ";")
  435. # Allocate some memory
  436. code.append("UA_ExtensionObject *" + self.getCodeInstanceName() + " = UA_ExtensionObject_new();")
  437. code.append(self.getCodeInstanceName() + "->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;")
  438. 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);")
  439. code.append("if(UA_ByteString_allocBuffer(&" + self.getCodeInstanceName() + "->content.encoded.body, 65000) != UA_STATUSCODE_GOOD) {}" )
  440. # Encode each value as a bytestring seperately.
  441. code.append("size_t " + self.getCodeInstanceName() + "_encOffset = 0;" )
  442. encFieldIdx = 0;
  443. for subv in self.value:
  444. encField = self.getEncodingRule()[encFieldIdx]
  445. encFieldIdx = encFieldIdx + 1;
  446. if encField[2] == 0:
  447. code.append("UA_" + subv.stringRepresentation + "_encodeBinary(&" + self.getCodeInstanceName()+"_struct."+subv.alias() + ", &" + self.getCodeInstanceName() + "->content.encoded.body, &" + self.getCodeInstanceName() + "_encOffset);" )
  448. else:
  449. if isinstance(subv, list):
  450. for subvidx in range(0,len(subv)):
  451. code.append("UA_" + subv.stringRepresentation + "_encodeBinary(&" + self.getCodeInstanceName()+"_struct."+subv.alias() + "[" + str(subvidx) + "], &" + self.getCodeInstanceName() + "->content.encoded.body, &" + self.getCodeInstanceName() + "_encOffset);" )
  452. else:
  453. code.append("UA_" + subv.stringRepresentation + "_encodeBinary(&" + self.getCodeInstanceName()+"_struct."+subv.alias() + "[0], &" + self.getCodeInstanceName() + "->content.encoded.body, &" + self.getCodeInstanceName() + "_encOffset);" )
  454. # Reallocate the memory by swapping the 65k Bytestring for a new one
  455. code.append(self.getCodeInstanceName() + "->content.encoded.body.length = " + self.getCodeInstanceName() + "_encOffset;");
  456. code.append("UA_Byte *" + self.getCodeInstanceName() + "_newBody = (UA_Byte *) UA_malloc(" + self.getCodeInstanceName() + "_encOffset );" )
  457. code.append("memcpy(" + self.getCodeInstanceName() + "_newBody, " + self.getCodeInstanceName() + "->content.encoded.body.data, " + self.getCodeInstanceName() + "_encOffset);" )
  458. code.append("UA_Byte *" + self.getCodeInstanceName() + "_oldBody = " + self.getCodeInstanceName() + "->content.encoded.body.data;");
  459. code.append(self.getCodeInstanceName() + "->content.encoded.body.data = " +self.getCodeInstanceName() + "_newBody;")
  460. code.append("UA_free(" + self.getCodeInstanceName() + "_oldBody);")
  461. code.append("")
  462. return code
  463. def printOpen62541CCode_SubType(self, asIndirect=True):
  464. if asIndirect == False:
  465. return "*" + str(self.getCodeInstanceName())
  466. return str(self.getCodeInstanceName())
  467. def __str__(self):
  468. return "'" + self.alias() + "':" + self.stringRepresentation + "(" + str(self.value) + ")"
  469. class opcua_BuiltinType_localizedtext_t(opcua_value_t):
  470. def setStringReprentation(self):
  471. self.stringRepresentation = "LocalizedText"
  472. def setNumericRepresentation(self):
  473. self.__binTypeId__ = BUILTINTYPE_TYPEID_LOCALIZEDTEXT
  474. def parseXML(self, xmlvalue):
  475. # Expect <LocalizedText> or <AliasName>
  476. # <Locale>xx_XX</Locale>
  477. # <Text>TextText</Text>
  478. # <LocalizedText> or </AliasName>
  479. #
  480. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  481. logger.error("Expected XML Element, but got junk...")
  482. return
  483. if self.alias() != None:
  484. if not self.alias() == xmlvalue.tagName:
  485. 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.")
  486. else:
  487. if not self.stringRepresentation == xmlvalue.tagName:
  488. 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.")
  489. if xmlvalue.firstChild == None:
  490. if self.alias() != None:
  491. logger.debug("Neither locale nor text in XML description field " + self.alias() + ". Setting to default ['en_US','']")
  492. else:
  493. logger.debug("Neither locale nor text in XML description. Setting to default ['en_US','']")
  494. self.value = ['en_US','']
  495. return
  496. self.value = []
  497. tmp = xmlvalue.getElementsByTagName("Locale")
  498. if len(tmp) == 0:
  499. logger.warn("Did not find a locale. Setting to en_US per default.")
  500. self.value.append('en_US')
  501. else:
  502. if tmp[0].firstChild == None:
  503. logger.warn("Locale tag without contents. Setting to en_US per default.")
  504. self.value.append('en_US')
  505. else:
  506. self.value.append(tmp[0].firstChild.data)
  507. clean = ""
  508. for s in self.value[0]:
  509. if s in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_":
  510. clean = clean + s
  511. self.value[0] = clean
  512. tmp = xmlvalue.getElementsByTagName("Text")
  513. if len(tmp) == 0:
  514. logger.warn("Did not find a Text. Setting to empty string per default.")
  515. self.value.append('')
  516. else:
  517. if tmp[0].firstChild == None:
  518. logger.warn("Text tag without content. Setting to empty string per default.")
  519. self.value.append('')
  520. else:
  521. self.value.append(tmp[0].firstChild.data)
  522. def printOpen62541CCode_SubType(self, asIndirect=True):
  523. if asIndirect==True:
  524. code = "UA_LOCALIZEDTEXT_ALLOC(\"" + str(self.value[0]) + "\", \"" + str(self.value[1].encode('utf-8')) + "\")"
  525. else:
  526. code = "UA_LOCALIZEDTEXT(\"" + str(self.value[0]) + "\", \"" + str(self.value[1].encode('utf-8')) + "\")"
  527. return code
  528. class opcua_BuiltinType_expandednodeid_t(opcua_value_t):
  529. def setStringReprentation(self):
  530. self.stringRepresentation = "ExpandedNodeId"
  531. def setNumericRepresentation(self):
  532. self.__binTypeId__ = BUILTINTYPE_TYPEID_EXPANDEDNODEID
  533. def parseXML(self, xmlvalue):
  534. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  535. logger.error("Expected XML Element, but got junk...")
  536. return
  537. logger.debug("Not implemented", LOG_LEVEL_ERR)
  538. def printOpen62541CCode_SubType(self, asIndirect=True):
  539. #FIXME! This one is definetely broken!
  540. code = ""
  541. return code
  542. class opcua_BuiltinType_nodeid_t(opcua_value_t):
  543. def setStringReprentation(self):
  544. self.stringRepresentation = "NodeId"
  545. def setNumericRepresentation(self):
  546. self.__binTypeId__ = BUILTINTYPE_TYPEID_NODEID
  547. def parseXML(self, xmlvalue):
  548. # Expect <NodeId> or <Alias>
  549. # <Identifier> # It is unclear whether or not this is manditory. Identifier tags are used in Namespace 0.
  550. # ns=x;i=y or similar string representation of id()
  551. # </Identifier>
  552. # </NodeId> or </Alias>
  553. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  554. logger.error("Expected XML Element, but got junk...")
  555. return
  556. if self.alias() != None:
  557. if not self.alias() == xmlvalue.tagName:
  558. 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.")
  559. else:
  560. if not self.stringRepresentation == xmlvalue.tagName:
  561. 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.")
  562. # Catch XML <NodeId />
  563. if xmlvalue.firstChild == None :
  564. logger.error("No value is given, which is illegal for Node Types...")
  565. self.value = None
  566. else:
  567. # Check if there is an <Identifier> tag
  568. if len(xmlvalue.getElementsByTagName("Identifier")) != 0:
  569. xmlvalue = xmlvalue.getElementsByTagName("Identifier")[0]
  570. self.value = self.parent.getNamespace().getNodeByIDString(unicode(xmlvalue.firstChild.data))
  571. if self.value == None:
  572. logger.error("Node with id " + str(unicode(xmlvalue.firstChild.data)) + " was not found in namespace.")
  573. def printOpen62541CCode_SubType(self, asIndirect=True):
  574. if self.value == None:
  575. return "UA_NODEID_NUMERIC(0,0)"
  576. nodeId = self.value.id()
  577. if nodeId.i != None:
  578. return "UA_NODEID_NUMERIC(" + str(nodeId.ns) + ", " + str(nodeId.i) + ")"
  579. elif nodeId.s != None:
  580. return "UA_NODEID_STRING(" + str(nodeId.ns) + ", " + str(nodeId.s) + ")"
  581. elif nodeId.b != None:
  582. logger.debug("NodeID Generation macro for bytestrings has not been implemented.")
  583. return "UA_NODEID_NUMERIC(0,0)"
  584. elif nodeId.g != None:
  585. logger.debug("NodeID Generation macro for guids has not been implemented.")
  586. return "UA_NODEID_NUMERIC(0,0)"
  587. return "UA_NODEID_NUMERIC(0,0)"
  588. class opcua_BuiltinType_datetime_t(opcua_value_t):
  589. def setStringReprentation(self):
  590. self.stringRepresentation = "DateTime"
  591. def setNumericRepresentation(self):
  592. self.__binTypeId__ = BUILTINTYPE_TYPEID_DATETIME
  593. def parseXML(self, xmlvalue):
  594. # Expect <DateTime> or <AliasName>
  595. # 2013-08-13T21:00:05.0000L
  596. # </DateTime> or </AliasName>
  597. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  598. logger.error("Expected XML Element, but got junk...")
  599. return
  600. if self.alias() != None:
  601. if not self.alias() == xmlvalue.tagName:
  602. 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.")
  603. else:
  604. if not self.stringRepresentation == xmlvalue.tagName:
  605. 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.")
  606. # Catch XML <DateTime /> by setting the value to a default
  607. if xmlvalue.firstChild == None :
  608. logger.debug("No value is given. Setting to default now()")
  609. self.value = strptime(strftime("%Y-%m-%dT%H:%M%S"), "%Y-%m-%dT%H:%M%S")
  610. else:
  611. timestr = unicode(xmlvalue.firstChild.data)
  612. # .NET tends to create this garbage %Y-%m-%dT%H:%M:%S.0000z
  613. # strip everything after the "." away for a posix time_struct
  614. if "." in timestr:
  615. timestr = timestr[:timestr.index(".")]
  616. # If the last character is not numeric, remove it
  617. while len(timestr)>0 and not timestr[-1] in "0123456789":
  618. timestr = timestr[:-1]
  619. try:
  620. self.value = strptime(timestr, "%Y-%m-%dT%H:%M:%S")
  621. except:
  622. logger.error("Timestring format is illegible. Expected 2001-01-30T21:22:23, but got " + timestr + " instead. Time will be defaultet to now()")
  623. self.value = strptime(strftime("%Y-%m-%dT%H:%M%S"), "%Y-%m-%dT%H:%M%S")
  624. class opcua_BuiltinType_qualifiedname_t(opcua_value_t):
  625. def setStringReprentation(self):
  626. self.stringRepresentation = "QualifiedName"
  627. def setNumericRepresentation(self):
  628. self.__binTypeId__ = BUILTINTYPE_TYPEID_QUALIFIEDNAME
  629. def parseXML(self, xmlvalue):
  630. # Expect <QualifiedName> or <AliasName>
  631. # <NamespaceIndex>Int16<NamespaceIndex> # Optional, apparently ommitted if ns=0 ??? (Not given in OPCUA Nodeset2)
  632. # <Name>SomeString<Name> # Speculation: Manditory if NamespaceIndex is given, omitted otherwise?
  633. # </QualifiedName> or </AliasName>
  634. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  635. logger.error("Expected XML Element, but got junk...")
  636. return
  637. if self.alias() != None:
  638. if not self.alias() == xmlvalue.tagName:
  639. 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.")
  640. else:
  641. if not self.stringRepresentation == xmlvalue.tagName:
  642. 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.")
  643. # Catch XML <Qalified /> by setting the value to a default
  644. if xmlvalue.firstChild == None :
  645. logger.debug("No value is given. Setting to default empty string in ns=0: [0, '']")
  646. self.value = [0, '']
  647. else:
  648. # Is a namespace index passed?
  649. if len(xmlvalue.getElementsByTagName("NamespaceIndex")) != 0:
  650. self.value = [int(xmlvalue.getElementsByTagName("NamespaceIndex")[0].firstChild.data)]
  651. # namespace index is passed and <Name> tags are now manditory?
  652. if len(xmlvalue.getElementsByTagName("Name")) != 0:
  653. self.value.append(xmlvalue.getElementsByTagName("Name")[0].firstChild.data)
  654. else:
  655. logger.debug("No name is specified, will default to empty string")
  656. self.value.append('')
  657. else:
  658. logger.debug("No namespace is specified, will default to 0")
  659. self.value = [0]
  660. self.value.append(unicode(xmlvalue.firstChild.data))
  661. def printOpen62541CCode_SubType(self, asIndirect=True):
  662. code = "UA_QUALIFIEDNAME_ALLOC(" + str(self.value[0]) + ", \"" + self.value[1].encode('utf-8') + "\")"
  663. return code
  664. class opcua_BuiltinType_statuscode_t(opcua_value_t):
  665. def setStringReprentation(self):
  666. self.stringRepresentation = "StatusCode"
  667. def setNumericRepresentation(self):
  668. self.__binTypeId__ = BUILTINTYPE_TYPEID_STATUSCODE
  669. def parseXML(self, xmlvalue):
  670. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  671. logger.error("Expected XML Element, but got junk...")
  672. return
  673. logger.warn("Not implemented")
  674. class opcua_BuiltinType_diagnosticinfo_t(opcua_value_t):
  675. def setStringReprentation(self):
  676. self.stringRepresentation = "StatusCode"
  677. def setNumericRepresentation(self):
  678. self.__binTypeId__ = BUILTINTYPE_TYPEID_DIAGNOSTICINFO
  679. def parseXML(self, xmlvalue):
  680. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  681. logger.error("Expected XML Element, but got junk...")
  682. return
  683. logger.warn("Not implemented")
  684. class opcua_BuiltinType_guid_t(opcua_value_t):
  685. def setStringReprentation(self):
  686. self.stringRepresentation = "Guid"
  687. def setNumericRepresentation(self):
  688. self.__binTypeId__ = BUILTINTYPE_TYPEID_GUID
  689. def parseXML(self, xmlvalue):
  690. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  691. logger.error("Expected XML Element, but got junk...")
  692. return
  693. if self.alias() != None:
  694. if not self.alias() == xmlvalue.tagName:
  695. 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.")
  696. else:
  697. if not self.stringRepresentation == xmlvalue.tagName:
  698. 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.")
  699. # Catch XML <Guid /> by setting the value to a default
  700. if xmlvalue.firstChild == None:
  701. logger.debug("No value is given. Setting to default 0")
  702. self.value = [0,0,0,0]
  703. else:
  704. self.value = unicode(xmlvalue.firstChild.data)
  705. self.value = self.value.replace("{","")
  706. self.value = self.value.replace("}","")
  707. self.value = self.value.split("-")
  708. tmp = []
  709. ok = True
  710. for g in self.value:
  711. try:
  712. tmp.append(int("0x"+g, 16))
  713. except:
  714. logger.error("Invalid formatting of Guid. Expected {01234567-89AB-CDEF-ABCD-0123456789AB}, got " + unicode(xmlvalue.firstChild.data))
  715. self.value = [0,0,0,0,0]
  716. ok = False
  717. if len(tmp) != 5:
  718. logger.error("Invalid formatting of Guid. Expected {01234567-89AB-CDEF-ABCD-0123456789AB}, got " + unicode(xmlvalue.firstChild.data))
  719. self.value = [0,0,0,0]
  720. ok = False
  721. self.value = tmp
  722. class opcua_BuiltinType_boolean_t(opcua_value_t):
  723. def setStringReprentation(self):
  724. self.stringRepresentation = "Boolean"
  725. def setNumericRepresentation(self):
  726. self.__binTypeId__ = BUILTINTYPE_TYPEID_BOOLEAN
  727. def parseXML(self, xmlvalue):
  728. # Expect <Boolean>value</Boolean> or
  729. # <Aliasname>value</Aliasname>
  730. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  731. logger.error("Expected XML Element, but got junk...")
  732. return
  733. if self.alias() != None:
  734. if not self.alias() == xmlvalue.tagName:
  735. 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.")
  736. else:
  737. if not self.stringRepresentation == xmlvalue.tagName:
  738. 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.")
  739. # Catch XML <Boolean /> by setting the value to a default
  740. if xmlvalue.firstChild == None:
  741. logger.debug("No value is given. Setting to default 0")
  742. self.value = "false"
  743. else:
  744. if "false" in unicode(xmlvalue.firstChild.data).lower():
  745. self.value = "false"
  746. else:
  747. self.value = "true"
  748. def printOpen62541CCode_SubType(self, asIndirect=True):
  749. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  750. class opcua_BuiltinType_byte_t(opcua_value_t):
  751. def setStringReprentation(self):
  752. self.stringRepresentation = "Byte"
  753. def setNumericRepresentation(self):
  754. self.__binTypeId__ = BUILTINTYPE_TYPEID_BYTE
  755. def parseXML(self, xmlvalue):
  756. # Expect <Byte>value</Byte> or
  757. # <Aliasname>value</Aliasname>
  758. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  759. logger.error("Expected XML Element, but got junk...")
  760. return
  761. if self.alias() != None:
  762. if not self.alias() == xmlvalue.tagName:
  763. 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.")
  764. else:
  765. if not self.stringRepresentation == xmlvalue.tagName:
  766. 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.")
  767. # Catch XML <Byte /> by setting the value to a default
  768. if xmlvalue.firstChild == None:
  769. logger.debug("No value is given. Setting to default 0")
  770. self.value = 0
  771. else:
  772. try:
  773. self.value = int(unicode(xmlvalue.firstChild.data))
  774. except:
  775. logger.error("Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data))
  776. def printOpen62541CCode_SubType(self, asIndirect=True):
  777. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  778. class opcua_BuiltinType_sbyte_t(opcua_value_t):
  779. def setStringReprentation(self):
  780. self.stringRepresentation = "SByte"
  781. def setNumericRepresentation(self):
  782. self.__binTypeId__ = BUILTINTYPE_TYPEID_SBYTE
  783. def parseXML(self, xmlvalue):
  784. # Expect <SByte>value</SByte> or
  785. # <Aliasname>value</Aliasname>
  786. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  787. logger.error("Expected XML Element, but got junk...")
  788. return
  789. if self.alias() != None:
  790. if not self.alias() == xmlvalue.tagName:
  791. 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.")
  792. else:
  793. if not self.stringRepresentation == xmlvalue.tagName:
  794. 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.")
  795. # Catch XML <SByte /> by setting the value to a default
  796. if xmlvalue.firstChild == None:
  797. logger.debug("No value is given. Setting to default 0")
  798. self.value = 0
  799. else:
  800. try:
  801. self.value = int(unicode(xmlvalue.firstChild.data))
  802. except:
  803. logger.error("Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data))
  804. def printOpen62541CCode_SubType(self, asIndirect=True):
  805. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  806. class opcua_BuiltinType_int16_t(opcua_value_t):
  807. def setStringReprentation(self):
  808. self.stringRepresentation = "Int16"
  809. def setNumericRepresentation(self):
  810. self.__binTypeId__ = BUILTINTYPE_TYPEID_INT16
  811. def parseXML(self, xmlvalue):
  812. # Expect <Int16>value</Int16> or
  813. # <Aliasname>value</Aliasname>
  814. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  815. logger.error("Expected XML Element, but got junk...")
  816. return
  817. if self.alias() != None:
  818. if not self.alias() == xmlvalue.tagName:
  819. 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.")
  820. else:
  821. if not self.stringRepresentation == xmlvalue.tagName:
  822. 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.")
  823. # Catch XML <Int16 /> by setting the value to a default
  824. if xmlvalue.firstChild == None:
  825. logger.debug("No value is given. Setting to default 0")
  826. self.value = 0
  827. else:
  828. try:
  829. self.value = int(unicode(xmlvalue.firstChild.data))
  830. except:
  831. logger.error("Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data))
  832. def printOpen62541CCode_SubType(self, asIndirect=True):
  833. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  834. class opcua_BuiltinType_uint16_t(opcua_value_t):
  835. def setStringReprentation(self):
  836. self.stringRepresentation = "UInt16"
  837. def setNumericRepresentation(self):
  838. self.__binTypeId__ = BUILTINTYPE_TYPEID_UINT16
  839. def parseXML(self, xmlvalue):
  840. # Expect <UInt16>value</UInt16> or
  841. # <Aliasname>value</Aliasname>
  842. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  843. logger.error("Expected XML Element, but got junk...")
  844. return
  845. if self.alias() != None:
  846. if not self.alias() == xmlvalue.tagName:
  847. 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.")
  848. else:
  849. if not self.stringRepresentation == xmlvalue.tagName:
  850. 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.")
  851. # Catch XML <UInt16 /> by setting the value to a default
  852. if xmlvalue.firstChild == None:
  853. logger.debug("No value is given. Setting to default 0")
  854. self.value = 0
  855. else:
  856. try:
  857. self.value = int(unicode(xmlvalue.firstChild.data))
  858. except:
  859. logger.error("Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data))
  860. def printOpen62541CCode_SubType(self, asIndirect=True):
  861. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  862. class opcua_BuiltinType_int32_t(opcua_value_t):
  863. def setStringReprentation(self):
  864. self.stringRepresentation = "Int32"
  865. def setNumericRepresentation(self):
  866. self.__binTypeId__ = BUILTINTYPE_TYPEID_INT32
  867. def parseXML(self, xmlvalue):
  868. # Expect <Int32>value</Int32> or
  869. # <Aliasname>value</Aliasname>
  870. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  871. logger.error("Expected XML Element, but got junk...")
  872. return
  873. if self.alias() != None:
  874. if not self.alias() == xmlvalue.tagName:
  875. 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.")
  876. else:
  877. if not self.stringRepresentation == xmlvalue.tagName:
  878. 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.")
  879. # Catch XML <Int32 /> by setting the value to a default
  880. if xmlvalue.firstChild == None:
  881. logger.debug("No value is given. Setting to default 0")
  882. self.value = 0
  883. else:
  884. try:
  885. self.value = int(unicode(xmlvalue.firstChild.data))
  886. except:
  887. logger.error("Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data))
  888. def printOpen62541CCode_SubType(self, asIndirect=True):
  889. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  890. class opcua_BuiltinType_uint32_t(opcua_value_t):
  891. def setStringReprentation(self):
  892. self.stringRepresentation = "UInt32"
  893. def setNumericRepresentation(self):
  894. self.__binTypeId__ = BUILTINTYPE_TYPEID_UINT32
  895. def parseXML(self, xmlvalue):
  896. # Expect <UInt32>value</UInt32> or
  897. # <Aliasname>value</Aliasname>
  898. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  899. logger.error("Expected XML Element, but got junk...")
  900. return
  901. if self.alias() != None:
  902. if not self.alias() == xmlvalue.tagName:
  903. 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.")
  904. else:
  905. if not self.stringRepresentation == xmlvalue.tagName:
  906. 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.")
  907. # Catch XML <UInt32 /> by setting the value to a default
  908. if xmlvalue.firstChild == None:
  909. logger.debug("No value is given. Setting to default 0")
  910. self.value = 0
  911. else:
  912. try:
  913. self.value = int(unicode(xmlvalue.firstChild.data))
  914. except:
  915. logger.error("Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data))
  916. def printOpen62541CCode_SubType(self, asIndirect=True):
  917. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  918. class opcua_BuiltinType_int64_t(opcua_value_t):
  919. def setStringReprentation(self):
  920. self.stringRepresentation = "Int64"
  921. def setNumericRepresentation(self):
  922. self.__binTypeId__ = BUILTINTYPE_TYPEID_INT64
  923. def parseXML(self, xmlvalue):
  924. # Expect <Int64>value</Int64> or
  925. # <Aliasname>value</Aliasname>
  926. if self.alias() != None:
  927. if not self.alias() == xmlvalue.tagName:
  928. 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.")
  929. else:
  930. if not self.stringRepresentation == xmlvalue.tagName:
  931. 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.")
  932. # Catch XML <Int64 /> by setting the value to a default
  933. if xmlvalue.firstChild == None:
  934. logger.debug("No value is given. Setting to default 0")
  935. self.value = 0
  936. else:
  937. try:
  938. self.value = int(unicode(xmlvalue.firstChild.data))
  939. except:
  940. logger.error("Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data))
  941. def printOpen62541CCode_SubType(self, asIndirect=True):
  942. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  943. class opcua_BuiltinType_uint64_t(opcua_value_t):
  944. def setStringReprentation(self):
  945. self.stringRepresentation = "UInt64"
  946. def setNumericRepresentation(self):
  947. self.__binTypeId__ = BUILTINTYPE_TYPEID_UINT64
  948. def parseXML(self, xmlvalue):
  949. # Expect <UInt16>value</UInt16> or
  950. # <Aliasname>value</Aliasname>
  951. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  952. logger.error("Expected XML Element, but got junk...")
  953. return
  954. if self.alias() != None:
  955. if not self.alias() == xmlvalue.tagName:
  956. 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.")
  957. else:
  958. if not self.stringRepresentation == xmlvalue.tagName:
  959. 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.")
  960. # Catch XML <UInt64 /> by setting the value to a default
  961. if xmlvalue.firstChild == None:
  962. logger.debug("No value is given. Setting to default 0")
  963. self.value = 0
  964. else:
  965. try:
  966. self.value = int(unicode(xmlvalue.firstChild.data))
  967. except:
  968. logger.error("Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data))
  969. def printOpen62541CCode_SubType(self, asIndirect=True):
  970. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  971. class opcua_BuiltinType_float_t(opcua_value_t):
  972. def setStringReprentation(self):
  973. self.stringRepresentation = "Float"
  974. def setNumericRepresentation(self):
  975. self.__binTypeId__ = BUILTINTYPE_TYPEID_FLOAT
  976. def parseXML(self, xmlvalue):
  977. # Expect <Float>value</Float> or
  978. # <Aliasname>value</Aliasname>
  979. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  980. logger.error("Expected XML Element, but got junk...")
  981. return
  982. if self.alias() != None:
  983. if not self.alias() == xmlvalue.tagName:
  984. 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.")
  985. else:
  986. if not self.stringRepresentation == xmlvalue.tagName:
  987. 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.")
  988. # Catch XML <Float /> by setting the value to a default
  989. if xmlvalue.firstChild == None:
  990. logger.debug("No value is given. Setting to default 0")
  991. self.value = 0.0
  992. else:
  993. try:
  994. self.value = float(unicode(xmlvalue.firstChild.data))
  995. except:
  996. logger.error("Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data))
  997. def printOpen62541CCode_SubType(self, asIndirect=True):
  998. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  999. class opcua_BuiltinType_double_t(opcua_value_t):
  1000. def setStringReprentation(self):
  1001. self.stringRepresentation = "Double"
  1002. def setNumericRepresentation(self):
  1003. self.__binTypeId__ = BUILTINTYPE_TYPEID_DOUBLE
  1004. def parseXML(self, xmlvalue):
  1005. # Expect <Double>value</Double> or
  1006. # <Aliasname>value</Aliasname>
  1007. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  1008. logger.error("Expected XML Element, but got junk...")
  1009. return
  1010. if self.alias() != None:
  1011. if not self.alias() == xmlvalue.tagName:
  1012. 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.")
  1013. else:
  1014. if not self.stringRepresentation == xmlvalue.tagName:
  1015. 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.")
  1016. # Catch XML <Double /> by setting the value to a default
  1017. if xmlvalue.firstChild == None:
  1018. logger.debug("No value is given. Setting to default 0")
  1019. self.value = 0.0
  1020. else:
  1021. try:
  1022. self.value = float(unicode(xmlvalue.firstChild.data))
  1023. except:
  1024. logger.error("Error parsing integer. Expected " + self.stringRepresentation + " but got " + unicode(xmlvalue.firstChild.data))
  1025. def printOpen62541CCode_SubType(self, asIndirect=True):
  1026. return "(UA_" + self.stringRepresentation + ") " + str(self.value)
  1027. class opcua_BuiltinType_string_t(opcua_value_t):
  1028. def setStringReprentation(self):
  1029. self.stringRepresentation = "String"
  1030. def setNumericRepresentation(self):
  1031. self.__binTypeId__ = BUILTINTYPE_TYPEID_STRING
  1032. def pack(self):
  1033. bin = structpack("I", len(unicode(self.value)))
  1034. bin = bin + str(self.value)
  1035. return bin
  1036. def parseXML(self, xmlvalue):
  1037. # Expect <String>value</String> or
  1038. # <Aliasname>value</Aliasname>
  1039. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  1040. logger.error("Expected XML Element, but got junk...")
  1041. return
  1042. if self.alias() != None:
  1043. if not self.alias() == xmlvalue.tagName:
  1044. 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.")
  1045. else:
  1046. if not self.stringRepresentation == xmlvalue.tagName:
  1047. 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.")
  1048. # Catch XML <String /> by setting the value to a default
  1049. if xmlvalue.firstChild == None:
  1050. logger.debug("No value is given. Setting to default 0")
  1051. self.value = ""
  1052. else:
  1053. self.value = str(unicode(xmlvalue.firstChild.data))
  1054. def printOpen62541CCode_SubType(self, asIndirect=True):
  1055. code = "UA_STRING_ALLOC(\"" + self.value.encode('utf-8') + "\")"
  1056. return code
  1057. class opcua_BuiltinType_xmlelement_t(opcua_BuiltinType_string_t):
  1058. def setStringReprentation(self):
  1059. self.stringRepresentation = "XmlElement"
  1060. def setNumericRepresentation(self):
  1061. self.__binTypeId__ = BUILTINTYPE_TYPEID_XMLELEMENT
  1062. def printOpen62541CCode_SubType(self, asIndirect=True):
  1063. code = "UA_XMLELEMENT_ALLOC(\"" + self.value.encode('utf-8') + "\")"
  1064. return code
  1065. class opcua_BuiltinType_bytestring_t(opcua_value_t):
  1066. def setStringReprentation(self):
  1067. self.stringRepresentation = "ByteString"
  1068. def setNumericRepresentation(self):
  1069. self.__binTypeId__ = BUILTINTYPE_TYPEID_BYTESTRING
  1070. def parseXML(self, xmlvalue):
  1071. # Expect <ByteString>value</ByteString> or
  1072. # <Aliasname>value</Aliasname>
  1073. if xmlvalue == None or xmlvalue.nodeType != xmlvalue.ELEMENT_NODE:
  1074. logger.error("Expected XML Element, but got junk...")
  1075. return
  1076. if self.alias() != None:
  1077. if not self.alias() == xmlvalue.tagName:
  1078. 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.")
  1079. else:
  1080. if not self.stringRepresentation == xmlvalue.tagName:
  1081. 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.")
  1082. # Catch XML <ByteString /> by setting the value to a default
  1083. if xmlvalue.firstChild == None:
  1084. logger.debug("No value is given. Setting to default 0")
  1085. self.value = ""
  1086. else:
  1087. self.value = str(unicode(xmlvalue.firstChild.data))
  1088. def printOpen62541CCode_SubType(self, asIndirect=True):
  1089. bs = ""
  1090. for line in self.value:
  1091. bs = bs + str(line).replace("\n","");
  1092. outs = bs
  1093. logger.debug("Encoded Bytestring: " + outs)
  1094. # bs = bs.decode('base64')
  1095. # outs = ""
  1096. # for s in bs:
  1097. # outs = outs + hex(ord(s)).upper().replace("0X", "\\x")
  1098. code = "UA_STRING_ALLOC(\"" + outs + "\")"
  1099. return code