ChimeraTK-ControlSystemAdapter-OPCUAAdapter  04.00.01
ua_node_types.py
Go to the documentation of this file.
1 #!/usr/bin/env/python
2 # -*- coding: utf-8 -*-
3 
4 # This Source Code Form is subject to the terms of the Mozilla Public
5 # License, v. 2.0. If a copy of the MPL was not distributed with this
6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 
8 
22 
23 import sys
24 import logging
25 from ua_builtin_types import *;
26 from open62541_MacroHelper import open62541_MacroHelper
27 from ua_constants import *
28 
29 logger = logging.getLogger(__name__)
30 
31 def getNextElementNode(xmlvalue):
32  if xmlvalue == None:
33  return None
34  xmlvalue = xmlvalue.nextSibling
35  while not xmlvalue == None and not xmlvalue.nodeType == xmlvalue.ELEMENT_NODE:
36  xmlvalue = xmlvalue.nextSibling
37  return xmlvalue
38 
39 
43 
45  """ Representation of a pointer.
46 
47  A pointer consists of a target (which should be a node class),
48  an optional reference type (which should be an instance of
49  opcua_node_referenceType_t) and an optional isForward flag.
50  """
51  __reference_type__ = None
52  __target__ = None
53  __isForward__ = True
54  __addr__ = 0
55  __parentNode__ = None
56 
57  def __init__(self, target, hidden=False, parentNode=None):
58  self.__target__ = target
59  self.__reference_type__ = None
60  self.__isForward__ = True
61  self.__isHidden__ = hidden
62  self.__parentNode__ = parentNode
63  self.__addr__ = 0
64 
65  def isHidden(self, data=None):
66  if isinstance(data, bool):
67  self.__isHidden__ = data
68  return self.__isHidden__
69 
70  def isForward(self, data=None):
71  if isinstance(data, bool):
72  self.__isForward__ = data
73  return self.__isForward__
74 
75  def referenceType(self, type=None):
76  if not type == None:
77  self.__reference_type__ = type
78  return self.__reference_type__
79 
80  def target(self, data=None):
81  if not data == None:
82  self.__target__ = data
83  return self.__target__
84 
85  def address(self, data=None):
86  if data != None:
87  self.__addr__ = data
88  return self.__addr__
89 
90  def parent(self):
91  return self.__parentNode__
92 
93  def getCodePrintableID(self):
94  src = "None"
95  tgt = "None"
96  type = "Unknown"
97  if self.parent() != None:
98  src = str(self.parent().id())
99  if self.target() != None:
100  tgt = str(self.target().id())
101  if self.referenceType() != None:
102  type = str(self.referenceType().id())
103  tmp = src+"_"+type+"_"+tgt
104  tmp = tmp.lower()
105  refid = ""
106  for i in tmp:
107  if not i in "ABCDEFGHIJKLMOPQRSTUVWXYZ0123456789".lower():
108  refid = refid + ("_")
109  else:
110  refid = refid + i
111  return refid
112 
113  def __str__(self):
114  retval=""
115  if isinstance(self.parent(), opcua_node_t):
116  if isinstance(self.parent().id(), opcua_node_id_t):
117  retval=retval + str(self.parent().id()) + "--["
118  else:
119  retval=retval + "(?) --["
120  else:
121  retval=retval + "(?) --["
122 
123  if isinstance(self.referenceType(), opcua_node_t):
124  retval=retval + str(self.referenceType().browseName()) + "]-->"
125  else:
126  retval=retval + "?]-->"
127 
128  if isinstance(self.target(), opcua_node_t):
129  if isinstance(self.target().id(), opcua_node_id_t):
130  retval=retval + str(self.target().id())
131  else:
132  retval=retval + "(?) "
133  else:
134  retval=retval + "(?) "
135 
136  if self.isForward() or self.isHidden():
137  retval = retval + " <"
138  if self.isForward():
139  retval = retval + "F"
140  if self.isHidden():
141  retval = retval + "H"
142  retval = retval + ">"
143  return retval
144 
145  def __repr__(self):
146  return self.__str__()
147 
148  def __cmp__(self, other):
149  if not isinstance(other, opcua_referencePointer_t):
150  return -1
151  if other.target() == self.target():
152  if other.referenceType() == self.referenceType():
153  if other.isForward() == self.isForward():
154  return 0
155  return 1
156 
157 
158 
161 
163  """ Implementation of a node ID.
164 
165  The ID will encoding itself appropriatly as string. If multiple ID's (numeric, string, guid)
166  are defined, the order of preference for the ID string is always numeric, guid,
167  bytestring, string. Binary encoding only applies to numeric values (UInt16).
168  """
169  i = -1
170  o = ""
171  g = ""
172  s = ""
173  ns = 0
174  __mystrname__ = ""
175 
176  def __init__(self, idstring):
177  idparts = idstring.split(";")
178  self.i = None
179  self.b = None
180  self.g = None
181  self.s = None
182  self.ns = 0
183  for p in idparts:
184  if p[:2] == "ns":
185  self.ns = int(p[3:])
186  elif p[:2] == "i=":
187  self.i = int(p[2:])
188  elif p[:2] == "o=":
189  self.b = p[2:]
190  elif p[:2] == "g=":
191  tmp = []
192  self.g = p[2:].split("-")
193  for i in self.g:
194  i = "0x"+i
195  tmp.append(int(i,16))
196  self.g = tmp
197  elif p[:2] == "s=":
198  self.s = p[2:]
199  self.__mystrname__ = ""
200  self.toString()
201 
202  def toString(self):
203  self.__mystrname__ = ""
204  if self.ns != 0:
205  self.__mystrname__ = "ns="+str(self.ns)+";"
206  # Order of preference is numeric, guid, bytestring, string
207  if self.i != None:
208  self.__mystrname__ = self.__mystrname__ + "i="+str(self.i)
209  elif self.g != None:
210  self.__mystrname__ = self.__mystrname__ + "g="
211  tmp = []
212  for i in self.g:
213  tmp.append(hex(i).replace("0x",""))
214  for i in tmp:
215  self.__mystrname__ = self.__mystrname__ + "-" + i
216  self.__mystrname__ = self.__mystrname__.replace("g=-","g=")
217  elif self.b != None:
218  self.__mystrname__ = self.__mystrname__ + "b="+str(self.b)
219  elif self.s != None:
220  self.__mystrname__ = self.__mystrname__ + "s="+str(self.s)
221 
222  def __str__(self):
223  return self.__mystrname__
224 
225  def __eq__(self, nodeId2):
226  if not nodeId2:
227  return False
228  return (self.toString() == nodeId2.toString())
229 
230  def __repr__(self):
231  return self.__mystrname__
232 
233 
236 
238  __node_id__ = None
239  __node_class__ = 0
240  __node_browseName__ = ""
241  __node_displayName__ = ""
242  __node_description__ = ""
243  __node_writeMask__ = 0
244  __node_userWriteMask__ = 0
245  __node_namespace__ = None
246  __node_references__ = []
247  __node_referencedBy__ = []
248  __binary__ = ""
249  __address__ = 0
250 
251  def __init__(self, id, ns):
252  self.__node_namespace__ = ns
253  self.__node_id__ = id
254  self.__node_class__ = 0
255  self.__node_browseName__ = ""
256  self.__node_displayName__ = ""
257  self.__node_description__ = ""
258  self.__node_writeMask__ = 0
259  self.__node_userWriteMask__ = 0
260  self.__node_references__ = []
261  self.__node_referencedBy__ = []
262  self.__init_subType__()
263  self.FLAG_ISABSTRACT = 128
264  self.FLAG_SYMMETRIC = 64
266  self.FLAG_EXECUTABLE = 16
269  self.__binary__ = ""
270 
271  def __init_subType__(self):
272  self.nodeClass(0)
273 
274  def __str__(self):
275  if isinstance(self.id(), opcua_node_id_t):
276  return self.__class__.__name__ + "(" + str(self.id()) + ")"
277  return self.__class__.__name__ + "( no ID )"
278 
279  def __repr__(self):
280  if isinstance(self.id(), opcua_node_id_t):
281  return self.__class__.__name__ + "(" + str(self.id()) + ")"
282  return self.__class__.__name__ + "( no ID )"
283 
284 
286  CodePrintable="NODE_"
287 
288  if isinstance(self.id(), opcua_node_id_t):
289  CodePrintable = self.__class__.__name__ + "_" + str(self.id())
290  else:
291  CodePrintable = self.__class__.__name__ + "_unknown_nid"
292 
293  CodePrintable = CodePrintable.lower()
294  cleanPrintable = ""
295  for i in range(0,len(CodePrintable)):
296  if not CodePrintable[i] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_".lower():
297  cleanPrintable = cleanPrintable + "_"
298  else:
299  cleanPrintable = cleanPrintable + CodePrintable[i]
300  return cleanPrintable
301 
302  def addReference(self, ref):
303  """ Add a opcua_referencePointer_t to the list of
304  references this node carries.
305  """
306  if not ref in self.__node_references__:
307  self.__node_references__.append(ref)
308 
309  def removeReference(self, ref):
310  if ref in self.__node_references__:
311  self.__node_references__.remove(ref)
312 
313  def removeReferenceToNode(self, targetNode):
314  tmp = []
315  if ref in self.__node_references__:
316  if ref.target() != targetNode:
317  tmp.append(ref)
318  self.__node_references__ = tmp
319 
320  def addInverseReferenceTarget(self, node):
321  """ Adds a reference to the inverse reference list of this node.
322 
323  Inverse references are considered as "this node is referenced by"
324  and facilitate lookups when between nodes that reference this node,
325  but are not referenced by this node. These references would
326  require the namespace to be traversed by references to be found
327  if this node was not aware of them.
328  """
329  # Only add this target if it is not already referenced
330  if not node in self.__node_referencedBy__:
331  if not self.hasReferenceTarget(node):
332  self.__node_referencedBy__.append(opcua_referencePointer_t(node, hidden=True, parentNode=self))
333 # logger.debug(self.__node_browseName__ + " added reverse reference to " + str(node.__node_browseName__))
334 # else:
335 # logger.debug(self.__node_browseName__ + " refusing reverse reference to " + str(node.__node_browseName__) + " (referenced normally)")
336 # else:
337 # logger.debug(self.__node_browseName__ + " refusing reverse reference to " + str(node.__node_browseName__) + " (already reversed referenced)")
338 
339  def getReferences(self):
340  return self.__node_references__
341 
343  return self.__node_referencedBy__
344 
345  def hasInverseReferenceTarget(self, node):
346  for r in self.getInverseReferences():
347  if node == r.target():
348  return True
349  return False
350 
351  def hasReferenceTarget(self, node):
352  for r in self.getReferences():
353  if node == r.target():
354  return True
355  return False
356 
358  """ getFirstParentNode
359 
360  return a tuple of (opcua_node_t, opcua_referencePointer_t) indicating
361  the first node found that references this node. If this node is not
362  referenced at all, None will be returned.
363 
364  This function requires a linked namespace.
365 
366  Note that there may be more than one nodes that reference this node.
367  The parent returned will be determined by the first isInverse()
368  Reference of this node found. If none exists, the first hidden
369  reference will be returned.
370  """
371  parent = None
372  revref = None
373 
374  for hiddenstatus in [False, True]:
375  for r in self.getReferences():
376  if r.isHidden() == hiddenstatus and r.isForward() == False:
377  parent = r.target()
378  for r in parent.getReferences():
379  if r.target() == self:
380  revref = r
381  break
382  if revref != None:
383  return (parent, revref)
384 
385  return (parent, revref)
386 
388  """ Updates inverse references in all nodes referenced by this node.
389 
390  The function will look up all referenced nodes and check if they
391  have a reference that points back at this node. If none is found,
392  that means that the target is not aware that this node references
393  it. In that case an inverse reference will be registered with
394  the target node to point back to this node instance.
395  """
396  # Update inverse references in all nodes we have referenced
397  for r in self.getReferences():
398  if isinstance(r.target(), opcua_node_t):
399  if not r.target().hasInverseReferenceTarget(self):
400  #logger.debug(self.__node_browseName__ + " req. rev. referencing in" + str(r.target().__node_browseName__))
401  r.target().addInverseReferenceTarget(self)
402  #else:
403  #logger.debug("Cannot register inverse link to " + str(r.target()) + " (not a node)")
404 
405  def id(self):
406  return self.__node_id__
407 
408  def getNamespace(self):
409  return self.__node_namespace__
410 
411  def nodeClass(self, c = 0):
412  """ Sets the node class attribute if c is passed.
413  Returns the current node class.
414  """
415  # Allow overwriting only if it is not set
416  if isinstance(c, int):
417  if self.__node_class__ == 0 and c < 256:
418  self.__node_class__ = c
419  return self.__node_class__
420 
421  def browseName(self, data=0):
422  """ Sets the browse name attribute if data is passed.
423  Returns the current browse name.
424  """
425  if isinstance(data, str):
426  self.__node_browseName__ = data
427  if sys.version_info[0] < 3:
428  return self.__node_browseName__.encode('utf-8')
429  return self.__node_browseName__
430 
431  def displayName(self, data=None):
432  """ Sets the display name attribute if data is passed.
433  Returns the current display name.
434  """
435  if data != None:
436  self.__node_displayName__ = data
437  return self.__node_displayName__.encode('utf-8')
438 
439  def description(self, data=None):
440  """ Sets the description attribute if data is passed.
441  Returns the current description.
442  """
443  if data != None:
444  self.__node_description__ = data
445  return self.__node_description__.encode('utf-8')
446 
447  def writeMask(self, data=None):
448  """ Sets the write mask attribute if data is passed.
449  Returns the current write mask.
450  """
451  if data != None:
452  self.__node_writeMask__ = data
453  return self.__node_writeMask__
454 
455  def userWriteMask(self, data=None):
456  """ Sets the user write mask attribute if data is passed.
457  Returns the current user write mask.
458  """
459  if data != None:
460  self.__node_userWriteMask__ = data
461  return self.__node_userWriteMask__
462 
463  def initiateDummyXMLReferences(self, xmlelement):
464  """ Initiates references found in the XML <References> element.
465 
466  All references initiated will be registered with this node, but
467  their targets will be strings extracted from the XML description
468  (hence "dummy").
469 
470  References created will however be registered with the namespace
471  for linkLater(), which will eventually replace the string target
472  with an actual instance of an opcua_node_t.
473  """
474  if not xmlelement.tagName == "References":
475  logger.error("XMLElement passed is not a reference list")
476  return
477  for ref in xmlelement.childNodes:
478  if ref.nodeType == ref.ELEMENT_NODE:
479  dummy = opcua_referencePointer_t(unicode(ref.firstChild.data), parentNode=self)
480  self.addReference(dummy)
481  self.getNamespace().linkLater(dummy)
482  for (at, av) in ref.attributes.items():
483  if at == "ReferenceType":
484  dummy.referenceType(av)
485  elif at == "IsForward":
486  if "false" in av.lower():
487  dummy.isForward(False)
488  else:
489  logger.error("Don't know how to process attribute " + at + "(" + av + ") for references.")
490 
491  def printDot(self):
492  cleanname = "node_" + str(self.id()).replace(";","").replace("=","")
493  dot = cleanname + " [label = \"{" + str(self.id()) + "|" + str(self.browseName()) + "}\", shape=\"record\"]"
494  for r in self.__node_references__:
495  if isinstance(r.target(), opcua_node_t):
496  tgtname = "node_" + str(r.target().id()).replace(";","").replace("=","")
497  dot = dot + "\n"
498  if r.isForward() == True:
499  dot = dot + cleanname + " -> " + tgtname + " [label=\"" + str(r.referenceType().browseName()) + "\"]\n"
500  else:
501  if len(r.referenceType().inverseName()) == 0:
502  logger.warn("Inverse name of reference is null " + str(r.referenceType().id()))
503  dot = dot + cleanname + " -> " + tgtname + " [label=\"" + str(r.referenceType().inverseName()) + "\"]\n"
504  return dot
505 
506  def sanitize(self):
507  """ Check the health of this node.
508 
509  Return True if all mandatory attributes are valid and all references have been
510  correclty linked to nodes. Returns False on failure, which should indicate
511  that this node needs to be removed from the namespace.
512  """
513  # Do we have an id?
514  if not isinstance(self.id(), opcua_node_id_t):
515  logger.error("HELP! I'm an id'less node!")
516  return False
517 
518  # Remove unlinked references
519  tmp = []
520  for r in self.getReferences():
521  if not isinstance(r, opcua_referencePointer_t):
522  logger.error("Reference is not a reference!?.")
523  elif not isinstance(r.referenceType(), opcua_node_t):
524  logger.error("Reference has no valid reference type and will be removed.")
525  elif not isinstance(r.target(), opcua_node_t):
526  logger.warn("Reference to " + str(r.target()) + " is not a node. It has been removed.")
527  else:
528  tmp.append(r)
529  self.__node_references__ = tmp
530 
531  # Make sure that every inverse referenced node actually does reference us
532  tmp = []
533  for r in self.getInverseReferences():
534  if not isinstance(r.target(), opcua_node_t):
535  logger.warn("Invers reference to " + str(r.target()) + " does not reference a real node. It has been removed.")
536  else:
537  if r.target().hasReferenceTarget(self):
538  tmp.append(r)
539  else:
540  logger.warn("Node " + str(self.id()) + " was falsely under the impression that it is referenced by " + str(r.target().id()))
541  self.__node_referencedBy__ = tmp
542 
543  # Remove references from inverse list if we can reach this not "the regular way"
544  # over a normal reference
545  tmp=[]
546  for r in self.getInverseReferences():
547  if not self.hasReferenceTarget(r.target()):
548  tmp.append(r)
549  else:
550  logger.debug("Removing unnecessary inverse reference to " + str(r.target.id()))
551  self.__node_referencedBy__ = tmp
552 
553  return self.sanitizeSubType()
554 
555  def sanitizeSubType(self):
556  pass
557 
558  def address(self, addr = None):
559  """ If addr is passed, the address of this node within the binary
560  representation will be set.
561 
562  If an address within the binary representation is known/set, this
563  function will return it. NoneType is returned if no address has been
564  set.
565  """
566  if addr != None:
567  self.__address__ = addr
568  return self.__address__
569 
570  def parseXML(self, xmlelement):
571  """ Extracts base attributes from the XML description of an element.
572  Parsed basetype attributes are:
573  * browseName
574  * displayName
575  * Description
576  * writeMask
577  * userWriteMask
578  * eventNotifier
579 
580  ParentNodeIds are ignored.
581 
582  If recognized, attributes and elements found will be removed from
583  the XML Element passed. Type-specific attributes and child elements
584  are handled by the parseXMLSubType() functions of all classes deriving
585  from this base type and will be called automatically.
586  """
587  thisxml = xmlelement
588  for (at, av) in thisxml.attributes.items():
589  if at == "NodeId":
590  xmlelement.removeAttribute(at)
591  elif at == "BrowseName":
592  self.browseName(str(av))
593  xmlelement.removeAttribute(at)
594  elif at == "DisplayName":
595  self.displayName(av)
596  xmlelement.removeAttribute(at)
597  elif at == "Description":
598  self.description(av)
599  xmlelement.removeAttribute(at)
600  elif at == "WriteMask":
601  self.writeMask(int(av))
602  xmlelement.removeAttribute(at)
603  elif at == "UserWriteMask":
604  self.userWriteMask(int(av))
605  xmlelement.removeAttribute(at)
606  elif at == "EventNotifier":
607  self.eventNotifier(int(av))
608  xmlelement.removeAttribute(at)
609  elif at == "ParentNodeId":
610  # Silently ignore this one..
611  xmlelement.removeAttribute(at)
612 
613  for x in thisxml.childNodes:
614  if x.nodeType == x.ELEMENT_NODE:
615  if x.firstChild:
616  if x.tagName == "BrowseName":
617  self.browseName(unicode(x.firstChild.data))
618  xmlelement.removeChild(x)
619  elif x.tagName == "DisplayName":
620  self.displayName(unicode(x.firstChild.data))
621  xmlelement.removeChild(x)
622  elif x.tagName == "Description":
623  self.description(unicode(x.firstChild.data))
624  xmlelement.removeChild(x)
625  elif x.tagName == "WriteMask":
626  self.writeMask(int(unicode(x.firstChild.data)))
627  xmlelement.removeChild(x)
628  elif x.tagName == "UserWriteMask":
629  self.userWriteMask(int(unicode(x.firstChild.data)))
630  xmlelement.removeChild(x)
631  if x.tagName == "References":
633  xmlelement.removeChild(x)
634  self.parseXMLSubType(xmlelement)
635 
636  def parseXMLSubType(self, xmlelement):
637  pass
638 
639  def printXML(self):
640  pass
641 
642  def printOpen62541CCode_SubtypeEarly(self, bootstrapping = True):
643  """ printOpen62541CCode_SubtypeEarly
644 
645  Initiate code segments for the nodes instantiotion that preceed
646  the actual UA_Server_addNode or UA_NodeStore_insert calls.
647  """
648  return []
649 
650  def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping = True):
651  """ printOpen62541CCode_Subtype
652 
653  Appends node type specific information to the nodes UA_Server_addNode
654  or UA_NodeStore_insert calls.
655  """
656  return []
657 
658  def printOpen62541CCode(self, unPrintedNodes=[], unPrintedReferences=[], supressGenerationOfAttribute=[]):
659  """ printOpen62541CCode
660 
661  Returns a list of strings containing the C-code necessary to intialize
662  this node for the open62541 OPC-UA Stack.
663 
664  Note that this function will fail if the nodeid is non-numeric, as
665  there is no UA_EXPANDEDNNODEID_[STRING|GUID|BYTESTRING] macro.
666  """
667  codegen = open62541_MacroHelper(supressGenerationOfAttribute=supressGenerationOfAttribute)
668  code = []
669  code.append("")
670  code.append("do {")
671 
672  # Just to be sure...
673  if not (self in unPrintedNodes):
674  logger.warn(str(self) + " attempted to reprint already printed node " + str(self)+ ".")
675  return []
676 
677  # If we are being passed a parent node by the namespace, use that for registering ourselves in the namespace
678  # Note: getFirstParentNode will return [parentNode, referenceToChild]
679  (parentNode, parentRef) = self.getFirstParentNode()
680  if not (parentNode in unPrintedNodes) and (parentNode != None) and (parentRef.referenceType() != None):
681  code.append("// Referencing node found and declared as parent: " + str(parentNode .id()) + "/" +
682  str(parentNode .__node_browseName__) + " using " + str(parentRef.referenceType().id()) +
683  "/" + str(parentRef.referenceType().__node_browseName__))
684  code = code + codegen.getCreateNodeNoBootstrap(self, parentNode, parentRef, unPrintedNodes)
685  # Parent to child reference is added by the server, do not reprint that reference
686  if parentRef in unPrintedReferences:
687  unPrintedReferences.remove(parentRef)
688  # the UA_Server_addNode function will use addReference which creates a bidirectional reference; remove any inverse
689  # references to our parent to avoid duplicate refs
690  for ref in self.getReferences():
691  if ref.target() == parentNode and ref.referenceType() == parentRef.referenceType() and ref.isForward() == False:
692  while ref in unPrintedReferences:
693  unPrintedReferences.remove(ref)
694  # Otherwise use the "Bootstrapping" method and we will get registered with other nodes later.
695  else:
696  code = code + self.printOpen62541CCode_SubtypeEarly(bootstrapping = True)
697  code = code + codegen.getCreateNodeBootstrap(self)
698  code = code + self.printOpen62541CCode_Subtype(unPrintedReferences = unPrintedReferences, bootstrapping = True)
699  code.append("// Parent node does not exist yet. This node will be bootstrapped and linked later.")
700  code.append("UA_RCU_LOCK();")
701  code.append("UA_NodeStore_insert(server->nodestore, (UA_Node*) " + self.getCodePrintableID() + ");")
702  code.append("UA_RCU_UNLOCK();")
703 
704  # Try to print all references to nodes that already exist
705  # Note: we know the reference types exist, because the namespace class made sure they were
706  # the first ones being printed
707  tmprefs = []
708  for r in self.getReferences():
709  #logger.debug("Checking if reference from " + str(r.parent()) + "can be created...")
710  if not (r.target() in unPrintedNodes):
711  if r in unPrintedReferences:
712  if (len(tmprefs) == 0):
713  code.append("// This node has the following references that can be created:")
714  code = code + codegen.getCreateStandaloneReference(self, r)
715  tmprefs.append(r)
716  # Remove printed refs from list
717  for r in tmprefs:
718  unPrintedReferences.remove(r)
719 
720  # Again, but this time check if other nodes deffered their node creation because this node did
721  # not exist...
722  tmprefs = []
723  for r in unPrintedReferences:
724  #logger.debug("Checking if another reference " + str(r.target()) + "can be created...")
725  if (r.target() == self) and not (r.parent() in unPrintedNodes):
726  if not isinstance(r.parent(), opcua_node_t):
727  logger.debug("Reference has no parent!")
728  elif not isinstance(r.parent().id(), opcua_node_id_t):
729  logger.debug("Parents nodeid is not a nodeID!")
730  else:
731  if (len(tmprefs) == 0):
732  code.append("// Creating this node has resolved the following open references:")
733  code = code + codegen.getCreateStandaloneReference(r.parent(), r)
734  tmprefs.append(r)
735  # Remove printed refs from list
736  for r in tmprefs:
737  unPrintedReferences.remove(r)
738 
739  # Again, just to be sure...
740  if self in unPrintedNodes:
741  # This is necessery to make printing work at all!
742  unPrintedNodes.remove(self)
743 
744  code.append("} while(0);")
745  return code
746 
748  __isAbstract__ = False
749  __symmetric__ = False
750  __reference_inverseName__ = ""
751  __reference_referenceType__ = None
752 
753  def __init_subType__(self):
754  self.nodeClass(NODE_CLASS_REFERENCETYPE)
755  self.__reference_isAbstract__ = False
756  self.__reference_symmetric__ = False
757  self.__reference_inverseName__ = ""
758  self.__reference_referenceType__ = None
759 
760  def referenceType(self,data=None):
761  if isinstance(data, opcua_node_t):
762  self.__reference_referenceType__ = data
763  return self.__reference_referenceType__
764 
765  def isAbstract(self,data=None):
766  if isinstance(data, bool):
767  self.__isAbstract__ = data
768  return self.__isAbstract__
769 
770  def symmetric(self,data=None):
771  if isinstance(data, bool):
772  self.__symmetric__ = data
773  return self.__symmetric__
774 
775  def inverseName(self,data=None):
776  if isinstance(data, str):
777  self.__reference_inverseName__ = data
778  return self.__reference_inverseName__
779 
780  def sanitizeSubType(self):
781  if not isinstance(self.referenceType(), opcua_referencePointer_t):
782  logger.error("ReferenceType " + str(self.referenceType()) + " of " + str(self.id()) + " is not a pointer (ReferenceType is mandatory for references).")
783  self.__reference_referenceType__ = None
784  return False
785  return True
786 
787  def parseXMLSubType(self, xmlelement):
788  for (at, av) in xmlelement.attributes.items():
789  if at == "Symmetric":
790  if "false" in av.lower():
791  self.symmetric(False)
792  else:
793  self.symmetric(True)
794  xmlelement.removeAttribute(at)
795  elif at == "InverseName":
796  self.inverseName(str(av))
797  xmlelement.removeAttribute(at)
798  elif at == "IsAbstract":
799  if "false" in str(av).lower():
800  self.isAbstract(False)
801  else:
802  self.isAbstract(True)
803  xmlelement.removeAttribute(at)
804  else:
805  logger.warn("Don't know how to process attribute " + at + " (" + av + ")")
806 
807  for x in xmlelement.childNodes:
808  if x.nodeType == x.ELEMENT_NODE:
809  if x.tagName == "InverseName" and x.firstChild:
810  self.inverseName(str(unicode(x.firstChild.data)))
811  else:
812  logger.warn( "Unprocessable XML Element: " + x.tagName)
813 
814  def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping = True):
815  code = []
816  codegen = open62541_MacroHelper()
817 
818  # Detect if this is bootstrapping or if we are attempting to use userspace...
819  if bootstrapping == False:
820  typeDefs = self.getNamespace().getSubTypesOf() # defaults to TypeDefinition
821  myTypeRef = None
822  for ref in self.getReferences():
823  if ref.referenceType() in typeDefs:
824  myTypeRef = ref
825  break
826  if myTypeRef==None:
827  for ref in self.getReferences():
828  if ref.referenceType().browseName() == "HasSubtype" and ref.isForward() == False:
829  myTypeRef = ref
830  break
831  if myTypeRef==None:
832  logger.warn(str(self) + " failed to locate a type definition, assuming BaseDataType.")
833  code.append(" // No valid typeDefinition found; assuming BaseDataType")
834  code.append(" UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE),")
835  else:
836  code.append(" " + codegen.getCreateExpandedNodeIDMacro(myTypeRef.target()) + ",")
837  while myTypeRef in unPrintedReferences:
838  unPrintedReferences.remove(myTypeRef)
839 
840  code.append(" UA_LOCALIZEDTEXT(\"\",\"" + str(self.inverseName()) + "\"),");
841  code.append(" // FIXME: Missing, isAbstract")
842  code.append(" // FIXME: Missing, symmetric")
843  return code
844 
845  if self.isAbstract():
846  code.append(self.getCodePrintableID() + "->isAbstract = true;")
847  if self.symmetric():
848  code.append(self.getCodePrintableID() + "->symmetric = true;")
849  if self.__reference_inverseName__ != "":
850  code.append(self.getCodePrintableID() + "->inverseName = UA_LOCALIZEDTEXT_ALLOC(\"en_US\", \"" + self.__reference_inverseName__ + "\");")
851  return code;
852 
853 
855  __object_eventNotifier__ = 0
856 
857  def __init_subType__(self):
858  self.nodeClass(NODE_CLASS_OBJECT)
859  self.__object_eventNotifier__ = 0
860 
861  def eventNotifier(self, data=""):
862  if isinstance(data, int):
863  self.__object_eventNotifier__ == data
864  return self.__object_eventNotifier__
865 
866  def parseXMLSubType(self, xmlelement):
867  for (at, av) in xmlelement.attributes.items():
868  if at == "EventNotifier":
869  self.eventNotifier(int(av))
870  xmlelement.removeAttribute(at)
871  elif at == "SymbolicName":
872  # Silently ignore this one
873  xmlelement.removeAttribute(at)
874  else:
875  logger.error("Don't know how to process attribute " + at + " (" + av + ")")
876 
877  for x in xmlelement.childNodes:
878  if x.nodeType == x.ELEMENT_NODE:
879  logger.info( "Unprocessable XML Element: " + x.tagName)
880 
881  def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping = True):
882  code = []
883  codegen = open62541_MacroHelper()
884 
885  # Detect if this is bootstrapping or if we are attempting to use userspace...
886  if bootstrapping == False:
887  typeDefs = self.getNamespace().getSubTypesOf() # defaults to TypeDefinition
888  myTypeRef = None
889  for ref in self.getReferences():
890  if ref.referenceType() in typeDefs:
891  myTypeRef = ref
892  break
893  if myTypeRef==None:
894  for ref in self.getReferences():
895  if ref.referenceType().browseName() == "HasSubtype" and ref.isForward() == False:
896  myTypeRef = ref
897  break
898  if myTypeRef==None:
899  logger.warn(str(self) + " failed to locate a type definition, assuming BaseObjectType.")
900  code.append(" // No valid typeDefinition found; assuming BaseObjectType")
901  code.append(" UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),")
902  else:
903  code.append(" " + codegen.getCreateExpandedNodeIDMacro(myTypeRef.target()) + ",")
904  while myTypeRef in unPrintedReferences:
905  unPrintedReferences.remove(myTypeRef)
906 
907  #FIXME: No event notifier in UA_Server_addNode call!
908  return code
909 
910  # We are being bootstrapped! Add the raw attributes to the node.
911  code.append(self.getCodePrintableID() + "->eventNotifier = (UA_Byte) " + str(self.eventNotifier()) + ";")
912  return code
913 
914 if sys.version_info[0] >= 3:
915  # strings are already parsed to unicode
916  def unicode(s):
917  return s
918 
920  __value__ = 0
921  __dataType__ = None
922  __valueRank__ = 0
923  __arrayDimensions__ = 0
924  __accessLevel__ = 0
925  __userAccessLevel__ = 0
926  __minimumSamplingInterval__ = 0
927  __historizing__ = False
928 
929  def __init_subType__(self):
930  self.nodeClass(NODE_CLASS_VARIABLE)
931  self.__value__ = None
932  self.__dataType__ = None
933  self.__valueRank__ = -1
934  self.__arrayDimensions__ = []
935  self.__accessLevel__ = 3
936  self.__userAccessLevel__ = 3
937  self.__minimumSamplingInterval__ = 0.0
938  self.__historizing__ = False
939  self.__xmlValueDef__ = None
940 
941  def value(self, data=0):
942  if isinstance(data, opcua_value_t):
943  self.__value__ = data
944  return self.__value__
945 
946  def dataType(self, data=None):
947  if data != None:
948  self.__dataType__ = data
949  return self.__dataType__
950 
951  def valueRank(self, data=""):
952  if isinstance(data, int):
953  self.__valueRank__ = data
954  return self.__valueRank__
955 
956  def arrayDimensions(self, data=None):
957  if not data==None:
958  self.__arrayDimensions__ = data
959  return self.__arrayDimensions__
960 
961  def accessLevel(self, data=None):
962  if not data==None:
963  self.__accessLevel__ = data
964  return self.__accessLevel__
965 
966  def userAccessLevel(self, data=None):
967  if not data==None:
968  self.__userAccessLevel__ = data
969  return self.__userAccessLevel__
970 
971  def minimumSamplingInterval(self, data=None):
972  if not data==None:
973  self.__minimumSamplingInterval__ = data
974  return self.__minimumSamplingInterval__
975 
976  def historizing(self, data=None):
977  if data != None:
978  self.__historizing__ = data
979  return self.__historizing__
980 
981  def sanitizeSubType(self):
982  if not isinstance(self.dataType(), opcua_referencePointer_t):
983  logger.error("DataType " + str(self.dataType()) + " of " + str(self.id()) + " is not a pointer (DataType is mandatory for variables).")
984  self.__dataType__ = None
985  return False
986 
987  if not isinstance(self.dataType().target(), opcua_node_t):
988  logger.error("DataType " + str(self.dataType().target()) + " of " + str(self.id()) + " does not point to a node (DataType is mandatory for variables).")
989  self.__dataType__ = None
990  return False
991  return True
992 
993  def allocateValue(self):
994  if not isinstance(self.dataType(), opcua_referencePointer_t):
995  logger.error("Variable " + self.browseName() + "/" + str(self.id()) + " does not reference a valid dataType.")
996  return False
997 
998  if not isinstance(self.dataType().target(), opcua_node_dataType_t):
999  logger.error("Variable " + self.browseName() + "/" + str(self.id()) + " does not have a valid dataType reference.")
1000  return False
1001 
1002  if not self.dataType().target().isEncodable():
1003  logger.error("DataType for Variable " + self.browseName() + "/" + str(self.id()) + " is not encodable.")
1004  return False
1005 
1006  # FIXME: Don't build at all or allocate "defaults"? I'm for not building at all.
1007  if self.__xmlValueDef__ == None:
1008  #logger.warn("Variable " + self.browseName() + "/" + str(self.id()) + " is not initialized. No memory will be allocated.")
1009  return False
1010 
1011  self.value(opcua_value_t(self))
1012  self.value().parseXML(self.__xmlValueDef__)
1013 
1014  # Array Dimensions must accurately represent the value and will be patched
1015  # reflect the exaxt dimensions attached binary stream.
1016  if not isinstance(self.value(), opcua_value_t) or len(self.value().value) == 0:
1017  self.arrayDimensions([])
1018  else:
1019  # Parser only permits 1-d arrays, which means we do not have to check further dimensions
1020  self.arrayDimensions([len(self.value().value)])
1021  return True
1022 
1023  def parseXMLSubType(self, xmlelement):
1024  for (at, av) in xmlelement.attributes.items():
1025  if at == "ValueRank":
1026  self.valueRank(int(av))
1027  xmlelement.removeAttribute(at)
1028  elif at == "AccessLevel":
1029  self.accessLevel(int(av))
1030  xmlelement.removeAttribute(at)
1031  elif at == "UserAccessLevel":
1032  self.userAccessLevel(int(av))
1033  xmlelement.removeAttribute(at)
1034  elif at == "MinimumSamplingInterval":
1035  self.minimumSamplingInterval(float(av))
1036  xmlelement.removeAttribute(at)
1037  elif at == "DataType":
1038  self.dataType(opcua_referencePointer_t(str(av), parentNode=self))
1039  # dataType needs to be linked to a node once the namespace is read
1040  self.getNamespace().linkLater(self.dataType())
1041  xmlelement.removeAttribute(at)
1042  elif at == "SymbolicName":
1043  # Silently ignore this one
1044  xmlelement.removeAttribute(at)
1045  else:
1046  logger.error("Don't know how to process attribute " + at + " (" + av + ")")
1047 
1048  for x in xmlelement.childNodes:
1049  if x.nodeType == x.ELEMENT_NODE:
1050  if x.tagName == "Value":
1051  # We need to be able to parse the DataType to build the variable value,
1052  # which can only be done if the namespace is linked.
1053  # Store the Value for later parsing
1054  self.__xmlValueDef__ = x
1055  #logger.debug( "Value description stored for later elaboration.")
1056  elif x.tagName == "DataType":
1057  self.dataType(opcua_referencePointer_t(str(av), parentNode=self))
1058  # dataType needs to be linked to a node once the namespace is read
1059  self.getNamespace().linkLater(self.dataType())
1060  elif x.tagName == "ValueRank":
1061  self.valueRank(int(unicode(x.firstChild.data)))
1062  elif x.tagName == "ArrayDimensions":
1063  self.arrayDimensions(int(unicode(x.firstChild.data)))
1064  elif x.tagName == "AccessLevel":
1065  self.accessLevel(int(unicode(x.firstChild.data)))
1066  elif x.tagName == "UserAccessLevel":
1067  self.userAccessLevel(int(unicode(x.firstChild.data)))
1068  elif x.tagName == "MinimumSamplingInterval":
1069  self.minimumSamplingInterval(float(unicode(x.firstChild.data)))
1070  elif x.tagName == "Historizing":
1071  if "true" in x.firstChild.data.lower():
1072  self.historizing(True)
1073  else:
1074  logger.info( "Unprocessable XML Element: " + x.tagName)
1075 
1076  def printOpen62541CCode_SubtypeEarly(self, bootstrapping = True):
1077  code = []
1078  # If we have an encodable value, try to encode that
1079  if self.dataType() != None and isinstance(self.dataType().target(), opcua_node_dataType_t):
1080  # Delegate the encoding of the datavalue to the helper if we have
1081  # determined a valid encoding
1082  if self.dataType().target().isEncodable():
1083  if self.value() != None:
1084  code = code + self.value().printOpen62541CCode(bootstrapping)
1085  return code
1086  if(bootstrapping):
1087  code.append("UA_Variant *" + self.getCodePrintableID() + "_variant = UA_alloca(sizeof(UA_Variant));")
1088  code.append("UA_Variant_init(" + self.getCodePrintableID() + "_variant);")
1089  return code
1090 
1091  def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping = True):
1092  code = []
1093  codegen = open62541_MacroHelper()
1094 
1095  # Detect if this is bootstrapping or if we are attempting to use userspace...
1096  if bootstrapping == False:
1097  code.append(" " + self.getCodePrintableID() + "_variant, ")
1098  code.append(" // FIXME: missing minimumSamplingInterval")
1099  code.append(" // FIXME: missing accessLevel")
1100  code.append(" // FIXME: missing userAccessLevel")
1101  code.append(" // FIXME: missing valueRank")
1102  return code
1103 
1104  if self.historizing():
1105  code.append(self.getCodePrintableID() + "->historizing = true;")
1106 
1107  code.append(self.getCodePrintableID() + "->minimumSamplingInterval = (UA_Double) " + str(self.minimumSamplingInterval()) + ";")
1108  code.append(self.getCodePrintableID() + "->userAccessLevel = (UA_Int32) " + str(self.userAccessLevel()) + ";")
1109  code.append(self.getCodePrintableID() + "->accessLevel = (UA_Int32) " + str(self.accessLevel()) + ";")
1110  code.append(self.getCodePrintableID() + "->valueRank = (UA_Int32) " + str(self.valueRank()) + ";")
1111  # The variant is guaranteed to exist by SubtypeEarly()
1112  code.append("UA_Variant_copy(" + self.getCodePrintableID() + "_variant, &" + self.getCodePrintableID() + "->value.data.value.value );")
1113  code.append(self.getCodePrintableID() + "->valueSource = UA_VALUESOURCE_DATA;")
1114  return code
1115 
1117  __executable__ = True
1118  __userExecutable__ = True
1119  __methodDecalaration__ = None
1120 
1121  def __init_subType__(self):
1122  self.nodeClass(NODE_CLASS_METHOD)
1123  self.__executable__ = True
1124  self.__userExecutable__ = True
1125  self.__methodDecalaration__ = None
1126 
1127  def methodDeclaration(self, data=None):
1128  if not data==None:
1129  self.__methodDecalaration__ = data
1130  return self.__methodDecalaration__
1131 
1132  def executable(self, data=None):
1133  if isinstance(data, bool):
1134  self.__executable__ == data
1135  return self.__executable__
1136 
1137  def userExecutable(self, data=None):
1138  if isinstance(data, bool):
1139  self.__userExecutable__ == data
1140  return self.__userExecutable__
1141 
1142  def sanitizeSubType(self):
1143  if self.methodDeclaration() != None:
1144  if not isinstance(self.methodDeclaration().target(), opcua_node_t):
1145  return False
1146  else:
1147  #FIXME: Is this even permitted!?
1148  pass
1149 
1150  def parseXMLSubType(self, xmlelement):
1151  for (at, av) in xmlelement.attributes.items():
1152  if at == "MethodDeclarationId":
1153  self.methodDeclaration(opcua_referencePointer_t(str(av), parentNode=self))
1154  # dataType needs to be linked to a node once the namespace is read
1155  self.getNamespace().linkLater(self.methodDeclaration())
1156  else:
1157  logger.error("Don't know how to process attribute " + at + " (" + av + ")")
1158 
1159  for x in xmlelement.childNodes:
1160  if x.nodeType == x.ELEMENT_NODE:
1161  logger.info( "Unprocessable XML Element: " + x.tagName)
1162 
1163  def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping = True):
1164  code = []
1165 
1166  # Detect if this is bootstrapping or if we are attempting to use userspace...
1167  if bootstrapping == False:
1168  code.append(" // Note: in/outputArguments are added by attaching the variable nodes,")
1169  code.append(" // not by including the in the addMethodNode() call.")
1170  code.append(" NULL,")
1171  code.append(" NULL,")
1172  code.append(" 0, NULL,")
1173  code.append(" 0, NULL,")
1174  code.append(" // FIXME: Missing executable")
1175  code.append(" // FIXME: Missing userExecutable")
1176  return code
1177 
1178  # UA_False is default for booleans on _init()
1179  if self.executable():
1180  code.append(self.getCodePrintableID() + "->executable = true;")
1181  if self.userExecutable():
1182  code.append(self.getCodePrintableID() + "->userExecutable = true;")
1183 
1184  return code
1185 
1187  __isAbstract__ = False
1188 
1189  def __init_subType__(self):
1190  self.nodeClass(NODE_CLASS_OBJECTTYPE)
1191  self.__isAbstract__ == False
1192 
1193  def isAbstract(self, data=None):
1194  if isinstance(data, bool):
1195  self.__isAbstract__ = data
1196  return self.__isAbstract__
1197 
1198  def parseXMLSubType(self, xmlelement):
1199  for (at, av) in xmlelement.attributes.items():
1200  if at == "IsAbstract":
1201  if "false" in av.lower():
1202  self.isAbstract(False)
1203  xmlelement.removeAttribute(at)
1204  else:
1205  logger.error("Don't know how to process attribute " + at + " (" + av + ")")
1206 
1207  for x in xmlelement.childNodes:
1208  if x.nodeType == x.ELEMENT_NODE:
1209  logger.info( "Unprocessable XML Element: " + x.tagName)
1210 
1211  def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping = True):
1212  code = []
1213  codegen = open62541_MacroHelper();
1214 
1215  # Detect if this is bootstrapping or if we are attempting to use userspace...
1216  if bootstrapping == False:
1217  typeDefs = self.getNamespace().getSubTypesOf() # defaults to TypeDefinition
1218  myTypeRef = None
1219  for ref in self.getReferences():
1220  if ref.referenceType() in typeDefs:
1221  myTypeRef = ref
1222  break
1223  if myTypeRef==None:
1224  for ref in self.getReferences():
1225  if ref.referenceType().browseName() == "HasSubtype" and ref.isForward() == False:
1226  myTypeRef = ref
1227  break
1228  if myTypeRef==None:
1229  logger.warn(str(self) + " failed to locate a type definition, assuming BaseObjectType.")
1230  code.append(" // No valid typeDefinition found; assuming BaseObjectType")
1231  code.append(" UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),")
1232  else:
1233  code.append(" " + codegen.getCreateExpandedNodeIDMacro(myTypeRef.target()) + ",")
1234  while myTypeRef in unPrintedReferences:
1235  code.append(" // removed " + str(myTypeRef))
1236  unPrintedReferences.remove(myTypeRef)
1237 
1238  if (self.isAbstract()):
1239  code.append(" true,")
1240  else:
1241  code.append(" false,")
1242 
1243  # Fallback mode for bootstrapping
1244  if (self.isAbstract()):
1245  code.append(self.getCodePrintableID() + "->isAbstract = true;")
1246 
1247  return code
1248 
1250  __value__ = 0
1251  __dataType__ = None
1252  __valueRank__ = 0
1253  __arrayDimensions__ = 0
1254  __isAbstract__ = False
1255  __xmlDefinition__ = None
1256 
1257  def __init_subType__(self):
1258  self.nodeClass(NODE_CLASS_VARIABLETYPE)
1259  self.__value__ = 0
1260  self.__dataType__ = None
1261  self.__valueRank__ = -1
1262  self.__arrayDimensions__ = 0
1263  self.__isAbstract__ = False
1264  self.__xmlDefinition__ = None
1265 
1266  def value(self, data=None):
1267  logger.error("Setting data not implemented!")
1268 
1269  def dataType(self, data=None):
1270  if data != None:
1271  self.__dataType__ = data
1272  return self.__dataType__
1273 
1274  def valueRank(self,data=None):
1275  if isinstance(data, int):
1276  self.__valueRank__ = data
1277  return self.__valueRank__
1278 
1279  def arrayDimensions(self,data=None):
1280  if isinstance(data, int):
1281  self.__arrayDimensions__ = data
1282  return self.__arrayDimensions__
1283 
1284  def isAbstract(self,data=None):
1285  if isinstance(data, bool):
1286  self.__isAbstract__ = data
1287  return self.__isAbstract__
1288 
1289  def sanitizeSubType(self):
1290  # DataType fields appear to be optional for VariableTypes
1291  # but if it does have a node set, it must obviously be a valid node
1292  if not self.dataType() != None:
1293  if not isinstance(self.dataType(), opcua_referencePointer_t):
1294  logger.error("DataType attribute of " + str(self.id()) + " is not a pointer")
1295  return False
1296  else:
1297  if not isinstance(self.dataType().target(), opcua_node_t):
1298  logger.error("DataType attribute of " + str(self.id()) + " does not point to a node")
1299  return False
1300  else:
1301  # FIXME: It's unclear wether this is ok or not.
1302  logger.warn("DataType attribute of variableType " + str(self.id()) + " is not defined.")
1303  return False
1304 
1305  def parseXMLSubType(self, xmlelement):
1306  for (at, av) in xmlelement.attributes.items():
1307  if at == "IsAbstract":
1308  if "false" in av.lower():
1309  self.isAbstract(False)
1310  else:
1311  self.isAbstract(True)
1312  xmlelement.removeAttribute(at)
1313  elif at == "ValueRank":
1314  self.valueRank(int(av))
1315  if self.valueRank() != -1:
1316  logger.warn("Array's or matrices are only permitted in variables and not supported for variableTypes. This attribute (" + at + "=" + av + ") will effectively be ignored.")
1317  xmlelement.removeAttribute(at)
1318  elif at == "DataType":
1319  self.dataType(opcua_referencePointer_t(str(av), parentNode=self))
1320  # dataType needs to be linked to a node once the namespace is read
1321  self.getNamespace().linkLater(self.dataType())
1322  else:
1323  logger.error("Don't know how to process attribute " + at + " (" + av + ")")
1324 
1325  for x in xmlelement.childNodes:
1326  if x.nodeType == x.ELEMENT_NODE:
1327  if x.tagName == "Definition":
1328  self.__xmlDefinition__ = x
1329  logger.debug( "Definition stored for future processing")
1330  else:
1331  logger.info( "Unprocessable XML Element: " + x.tagName)
1332 
1333  def printOpen62541CCode_SubtypeEarly(self, bootstrapping = True):
1334  code = []
1335  # If we have an encodable value, try to encode that
1336  if self.dataType() != None and isinstance(self.dataType().target(), opcua_node_dataType_t):
1337  # Delegate the encoding of the datavalue to the helper if we have
1338  # determined a valid encoding
1339  if self.dataType().target().isEncodable():
1340  if self.value() != None:
1341  code = code + self.value().printOpen62541CCode(bootstrapping)
1342  return code
1343  if(bootstrapping):
1344  code.append("UA_Variant *" + self.getCodePrintableID() + "_variant = UA_alloca(sizeof(UA_Variant));")
1345  code.append("UA_Variant_init(" + self.getCodePrintableID() + "_variant);")
1346  return code
1347 
1348  def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping = True):
1349  code = []
1350  codegen = open62541_MacroHelper()
1351 
1352  if bootstrapping == False:
1353  code.append(" " + self.getCodePrintableID() + "_variant, ")
1354  code.append(" " + str(self.valueRank()) + ",")
1355  if self.isAbstract():
1356  code.append(" true,")
1357  else:
1358  code.append(" false,")
1359  return code
1360 
1361  if (self.isAbstract()):
1362  code.append(self.getCodePrintableID() + "->isAbstract = true;")
1363  else:
1364  code.append(self.getCodePrintableID() + "->isAbstract = false;")
1365 
1366  # The variant is guaranteed to exist by SubtypeEarly()
1367  code.append("UA_Variant_copy(" + self.getCodePrintableID() + "_variant, &" + self.getCodePrintableID() + "->value.data.value.value );")
1368  code.append(self.getCodePrintableID() + "->valueSource = UA_VALUESOURCE_DATA;")
1369  return code
1370 
1372  """ opcua_node_dataType_t is a subtype of opcua_note_t describing DataType nodes.
1373 
1374  DataType contain definitions and structure information usable for Variables.
1375  The format of this structure is determined by buildEncoding()
1376  Two definition styles are distinguished in XML:
1377  1) A DataType can be a structure of fields, each field having a name and a type.
1378  The type must be either an encodable builtin node (ex. UInt32) or point to
1379  another DataType node that inherits its encoding from a builtin type using
1380  a inverse "hasSubtype" (hasSuperType) reference.
1381  2) A DataType may be an enumeration, in which each field has a name and a numeric
1382  value.
1383  The definition is stored as an ordered list of tuples. Depending on which
1384  definition style was used, the __definition__ will hold
1385  1) A list of ("Fieldname", opcua_node_t) tuples.
1386  2) A list of ("Fieldname", int) tuples.
1387 
1388  A DataType (and in consequence all Variables using it) shall be deemed not
1389  encodable if any of its fields cannot be traced to an encodable builtin type.
1390 
1391  A DataType shall be further deemed not encodable if it contains mixed structure/
1392  enumaration definitions.
1393 
1394  If encodable, the encoding can be retrieved using getEncoding().
1395  """
1396  __isAbstract__ = False
1397  __isEnum__ = False
1398  __xmlDefinition__ = None
1399  __baseTypeEncoding__ = []
1400  __encodable__ = False
1401  __encodingBuilt__ = False
1402  __definition__ = []
1403 
1404  def __init_subType__(self):
1405  self.nodeClass(NODE_CLASS_DATATYPE)
1406  self.__isAbstract__ == False
1407  self.__xmlDefinition__ = None
1408  self.__baseTypeEncoding__ = []
1409  self.__encodable__ = None
1410  self.__encodingBuilt__ = False
1411  self.__definition__ = []
1412  self.__isEnum__ = False
1413 
1414  def isAbstract(self,data=None):
1415  """ Will return True if isAbstract was defined.
1416 
1417  Calling this function with an arbitrary data parameter will set
1418  isAbstract = data.
1419  """
1420  if isinstance(data, bool):
1421  self.__isAbstract__ = data
1422  return self.__isAbstract__
1423 
1424  def isEncodable(self):
1425  """ Will return True if buildEncoding() was able to determine which builtin
1426  type corresponds to all fields of this DataType.
1427 
1428  If no encoding has been build yet, this function will call buildEncoding()
1429  and return True if it succeeds.
1430  """
1431  return self.__encodable__
1432 
1433  def getEncoding(self):
1434  """ If the dataType is encodable, getEncoding() returns a nested list
1435  containing the encoding the structure definition for this type.
1436 
1437  If no encoding has been build yet, this function will call buildEncoding()
1438  and return the encoding if buildEncoding() succeeds.
1439 
1440  If buildEncoding() fails or has failed, an empty list will be returned.
1441  """
1442  if self.__encodable__ == False:
1443  if self.__encodingBuilt__ == False:
1444  return self.buildEncoding()
1445  return []
1446  else:
1447  return self.__baseTypeEncoding__
1448 
1449  def buildEncoding(self, indent=0, force=False):
1450  """ buildEncoding() determines the structure and aliases used for variables
1451  of this DataType.
1452 
1453  The function will parse the XML <Definition> of the dataType and extract
1454  "Name"-"Type" tuples. If successfull, buildEncoding will return a nested
1455  list of the following format:
1456 
1457  [['Alias1', ['Alias2', ['BuiltinType']]], [Alias2, ['BuiltinType']], ...]
1458 
1459  Aliases are fieldnames defined by this DataType or DataTypes referenced. A
1460  list such as ['DataPoint', ['Int32']] indicates that a value will encode
1461  an Int32 with the alias 'DataPoint' such as <DataPoint>12827</DataPoint>.
1462  Only the first Alias of a nested list is considered valid for the BuiltinType.
1463 
1464  Single-Elemented lists are always BuiltinTypes. Every nested list must
1465  converge in a builtin type to be encodable. buildEncoding will follow
1466  the first type inheritance reference (hasSupertype) of the dataType if
1467  necessary;
1468 
1469  If instead to "DataType" a numeric "Value" attribute is encountered,
1470  the DataType will be considered an enumeration and all Variables using
1471  it will be encoded as Int32.
1472 
1473  DataTypes can be either structures or enumeration - mixed definitions will
1474  be unencodable.
1475 
1476  Calls to getEncoding() will be iterative. buildEncoding() can be called
1477  only once per dataType, with all following calls returning the predetermined
1478  value. Use of the 'force=True' parameter will force the Definition to be
1479  reparsed.
1480 
1481  After parsing, __definition__ holds the field definition as a list. Note
1482  that this might deviate from the encoding, especially if inheritance was
1483  used.
1484  """
1485 
1486  proxy = opcua_value_t(None)
1487  prefix = " " + "|"*indent+ "+"
1488 
1489  if force==True:
1490  self.__encodingBuilt__ = False
1491 
1492  if self.__encodingBuilt__ == True:
1493  if self.isEncodable():
1494  logger.debug(prefix + str(self.__baseTypeEncoding__) + " (already analyzed)")
1495  else:
1496  logger.debug( prefix + str(self.__baseTypeEncoding__) + "(already analyzed, not encodable!)")
1497  return self.__baseTypeEncoding__
1498  self.__encodingBuilt__ = True # signify that we have attempted to built this type
1499  self.__encodable__ = True
1500 
1501  if indent==0:
1502  logger.debug("Parsing DataType " + self.browseName() + " (" + str(self.id()) + ")")
1503 
1504  if proxy.isBuiltinByString(self.browseName()):
1505  self.__baseTypeEncoding__ = [self.browseName()]
1506  self.__encodable__ = True
1507  logger.debug( prefix + self.browseName() + "*")
1508  logger.debug("Encodable as: " + str(self.__baseTypeEncoding__))
1509  logger.debug("")
1510  return self.__baseTypeEncoding__
1511 
1512  if self.__xmlDefinition__ == None:
1513  # Check if there is a supertype available
1514  for ref in self.getReferences():
1515  if "hassubtype" in ref.referenceType().browseName().lower() and ref.isForward() == False:
1516  if isinstance(ref.target(), opcua_node_dataType_t):
1517  logger.debug( prefix + "Attempting definition using supertype " + ref.target().browseName() + " for DataType " + " " + self.browseName())
1518  subenc = ref.target().buildEncoding(indent=indent+1)
1519  if not ref.target().isEncodable():
1520  self.__encodable__ = False
1521  break
1522  else:
1523  self.__baseTypeEncoding__ = self.__baseTypeEncoding__ + [self.browseName(), subenc, 0]
1524  if len(self.__baseTypeEncoding__) == 0:
1525  logger.debug(prefix + "No viable definition for " + self.browseName() + " " + str(self.id()) + " found.")
1526  self.__encodable__ = False
1527 
1528  if indent==0:
1529  if not self.__encodable__:
1530  logger.debug("Not encodable (partial): " + str(self.__baseTypeEncoding__))
1531  else:
1532  logger.debug("Encodable as: " + str(self.__baseTypeEncoding__))
1533  logger.debug( "")
1534 
1535  return self.__baseTypeEncoding__
1536 
1537  isEnum = True
1538  isSubType = True
1539  hasValueRank = 0
1540 
1541  # We need to store the definition as ordered data, but can't use orderedDict
1542  # for backward compatibility with Python 2.6 and 3.4
1543  enumDict = []
1544  typeDict = []
1545 
1546  # An XML Definition is provided and will be parsed... now
1547  for x in self.__xmlDefinition__.childNodes:
1548  if x.nodeType == x.ELEMENT_NODE:
1549  fname = ""
1550  fdtype = ""
1551  enumVal = ""
1552  hasValueRank = 0
1553  for at,av in x.attributes.items():
1554  if at == "DataType":
1555  fdtype = str(av)
1556  isEnum = False
1557  elif at == "Name":
1558  fname = str(av)
1559  elif at == "Value":
1560  enumVal = int(av)
1561  isSubType = False
1562  elif at == "ValueRank":
1563  hasValueRank = int(av)
1564  logger.warn("Arrays or matrices (ValueRank) are not supported for datatypes. This DT will become scalar.")
1565  else:
1566  logger.warn("Unknown Field Attribute " + str(at))
1567  # This can either be an enumeration OR a structure, not both.
1568  # Figure out which of the dictionaries gets the newly read value pair
1569  if isEnum == isSubType:
1570  # This is an error
1571  logger.warn("DataType contains both enumeration and subtype (or neither)")
1572  self.__encodable__ = False
1573  break
1574  elif isEnum:
1575  # This is an enumeration
1576  enumDict.append((fname, enumVal))
1577  continue
1578  else:
1579  # This might be a subtype... follow the node defined as datatype to find out
1580  # what encoding to use
1581  dtnode = self.getNamespace().getNodeByIDString(fdtype)
1582  if dtnode == None:
1583  # Node found in datatype element is invalid
1584  logger.debug( prefix + fname + " ?? " + av + " ??")
1585  self.__encodable__ = False
1586  else:
1587  # The node in the datatype element was found. we inherit its encoding,
1588  # but must still ensure that the dtnode is itself validly encodable
1589  typeDict.append([fname, dtnode])
1590  if hasValueRank < 0:
1591  hasValueRank = 0
1592  fdtype = str(dtnode.browseName()) + "+"*hasValueRank
1593  logger.debug( prefix + fname + " : " + fdtype + " -> " + str(dtnode.id()))
1594  subenc = dtnode.buildEncoding(indent=indent+1)
1595  self.__baseTypeEncoding__ = self.__baseTypeEncoding__ + [[fname, subenc, hasValueRank]]
1596  if not dtnode.isEncodable():
1597  # If we inherit an encoding from an unencodable not, this node is
1598  # also not encodable
1599  self.__encodable__ = False
1600  break
1601 
1602  # If we used inheritance to determine an encoding without alias, there is a
1603  # the possibility that lists got double-nested despite of only one element
1604  # being encoded, such as [['Int32']] or [['alias',['int32']]]. Remove that
1605  # enclosing list.
1606  while len(self.__baseTypeEncoding__) == 1 and isinstance(self.__baseTypeEncoding__[0], list):
1608 
1609  if isEnum == True:
1610  self.__baseTypeEncoding__ = self.__baseTypeEncoding__ + ['Int32']
1611  self.__definition__ = enumDict
1612  self.__isEnum__ = True
1613  logger.debug( prefix+"Int32* -> enumeration with dictionary " + str(enumDict) + " encodable " + str(self.__encodable__))
1614  return self.__baseTypeEncoding__
1615 
1616  if indent==0:
1617  if not self.__encodable__:
1618  logger.debug( "Not encodable (partial): " + str(self.__baseTypeEncoding__))
1619  else:
1620  logger.debug( "Encodable as: " + str(self.__baseTypeEncoding__))
1621  self.__isEnum__ = False
1622  self.__definition__ = typeDict
1623  logger.debug( "")
1624  return self.__baseTypeEncoding__
1625 
1626  def parseXMLSubType(self, xmlelement):
1627  """ Parses all XML data that is not considered part of the base node attributes.
1628 
1629  XML attributes fields processed are "isAbstract"
1630  XML elements processed are "Definition"
1631  """
1632  for (at, av) in xmlelement.attributes.items():
1633  if at == "IsAbstract":
1634  if "true" in str(av).lower():
1635  self.isAbstract(True)
1636  else:
1637  self.isAbstract(False)
1638  xmlelement.removeAttribute(at)
1639  else:
1640  logger.warn("Don't know how to process attribute " + at + " (" + av + ")")
1641 
1642  for x in xmlelement.childNodes:
1643  if x.nodeType == x.ELEMENT_NODE:
1644  if x.tagName == "Definition":
1645  self.__xmlDefinition__ = x
1646  #logger.debug( "Definition stored for future processing")
1647  else:
1648  logger.warn( "Unprocessable XML Element: " + x.tagName)
1649 
1650  def encodedTypeId(self):
1651  """ Returns a number of the builtin Type that should be used
1652  to represent this datatype.
1653  """
1654  if self.isEncodable() != True or len(self.getEncoding()) == 0:
1655  # Encoding is []
1656  return 0
1657  else:
1658  enc = self.getEncoding()
1659  if len(enc) > 1 and isinstance(enc[0], list):
1660  # [ [?], [?], [?] ]
1661  # Encoding is a list representing an extensionobject
1662  return opcua_BuiltinType_extensionObject_t(None).getNumericRepresentation()
1663  else:
1664  if len(enc)==1 and isinstance(enc[0], str):
1665  # [ 'BuiltinType' ]
1666  return opcua_value_t(None).getTypeByString(enc[0]).getNumericRepresentation()
1667  else:
1668  # [ ['Alias', [?]] ]
1669  # Determine if [?] is reducable to a builtin type or if [?] is an aliased
1670  # extensionobject
1671  while len(enc) > 1 and isinstance(enc[0], str):
1672  enc = enc[1]
1673  if len(enc) > 1:
1674  return opcua_BuiltinType_extensionObject_t(None).getNumericRepresentation()
1675  else:
1676  return opcua_value_t(None).getTypeByString(enc[0]).getNumericRepresentation()
1677 
1678  def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping = True):
1679  code = []
1680  codegen = open62541_MacroHelper()
1681 
1682  # Detect if this is bootstrapping or if we are attempting to use userspace...
1683  if bootstrapping == False:
1684  typeDefs = self.getNamespace().getSubTypesOf() # defaults to TypeDefinition
1685  myTypeRef = None
1686  for ref in self.getReferences():
1687  if ref.referenceType() in typeDefs:
1688  myTypeRef = ref
1689  break
1690  if myTypeRef==None:
1691  for ref in self.getReferences():
1692  if ref.referenceType().browseName() == "HasSubtype" and ref.isForward() == False:
1693  myTypeRef = ref
1694  break
1695  if myTypeRef==None:
1696  logger.warn(str(self) + " failed to locate a type definition, assuming BaseDataType.")
1697  code.append(" // No valid typeDefinition found; assuming BaseDataType")
1698  code.append(" UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE),")
1699  else:
1700  code.append(" " + codegen.getCreateExpandedNodeIDMacro(myTypeRef.target()) + ",")
1701  while myTypeRef in unPrintedReferences:
1702  unPrintedReferences.remove(myTypeRef)
1703 
1704  if (self.isAbstract()):
1705  code.append(" true,")
1706  else:
1707  code.append(" false,")
1708  return code
1709 
1710  if (self.isAbstract()):
1711  code.append(self.getCodePrintableID() + "->isAbstract = true;")
1712  else:
1713  code.append(self.getCodePrintableID() + "->isAbstract = false;")
1714  return code
1715 
1717  __containsNoLoops__ = True
1718  __eventNotifier__ = 0
1719 
1720  def __init_subType__(self):
1721  self.nodeClass(NODE_CLASS_VIEW)
1722  self.__containsNoLoops__ == False
1723  self.__eventNotifier__ == False
1724 
1725  def containsNoLoops(self,data=None):
1726  if isinstance(data, bool):
1727  self.__containsNoLoops__ = data
1728  return self.__containsNoLoops__
1729 
1730  def eventNotifier(self,data=None):
1731  if isinstance(data, int):
1732  self.__eventNotifier__ = data
1733  return self.__eventNotifier__
1734 
1735  def parseXMLSubtype(self, xmlelement):
1736  for (at, av) in xmlelement.attributes.items():
1737  logger.error("Don't know how to process attribute " + at + " (" + av + ")")
1738 
1739  for x in xmlelement.childNodes:
1740  if x.nodeType == x.ELEMENT_NODE:
1741  logger.info( "Unprocessable XML Element: " + x.tagName)
1742 
1743  def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping = True):
1744  code = []
1745  codegen = open62541_MacroHelper()
1746 
1747  # Detect if this is bootstrapping or if we are attempting to use userspace...
1748  if bootstrapping == False:
1749  typeDefs = self.getNamespace().getSubTypesOf() # defaults to TypeDefinition
1750  myTypeRef = None
1751  for ref in self.getReferences():
1752  if ref.referenceType() in typeDefs:
1753  myTypeRef = ref
1754  break
1755  if myTypeRef==None:
1756  for ref in self.getReferences():
1757  if ref.referenceType().browseName() == "HasSubtype" and ref.isForward() == False:
1758  myTypeRef = ref
1759  break
1760  if myTypeRef==None:
1761  logger.warn(str(self) + " failed to locate a type definition, assuming BaseViewType.")
1762  code.append(" // No valid typeDefinition found; assuming BaseViewType")
1763  code.append(" UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEViewTYPE),")
1764  else:
1765  code.append(" " + codegen.getCreateExpandedNodeIDMacro(myTypeRef.target()) + ",")
1766  while myTypeRef in unPrintedReferences:
1767  unPrintedReferences.remove(myTypeRef)
1768 
1769  code.append(" // FIXME: Missing eventNotifier")
1770  code.append(" // FIXME: Missing containsNoLoops")
1771  return code
1772 
1773  if self.containsNoLoops():
1774  code.append(self.getCodePrintableID() + "->containsNoLoops = true;")
1775  else:
1776  code.append(self.getCodePrintableID() + "->containsNoLoops = false;")
1777 
1778  code.append(self.getCodePrintableID() + "->eventNotifier = (UA_Byte) " + str(self.eventNotifier()) + ";")
1779 
1780  return code
ua_node_types.opcua_node_dataType_t.printOpen62541CCode_Subtype
def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping=True)
Definition: ua_node_types.py:1678
ua_node_types.opcua_node_t.hasReferenceTarget
def hasReferenceTarget(self, node)
Definition: ua_node_types.py:351
ua_node_types.opcua_node_t.__node_writeMask__
int __node_writeMask__
Definition: ua_node_types.py:243
ua_node_types.opcua_node_referenceType_t.__reference_isAbstract__
__reference_isAbstract__
Definition: ua_node_types.py:755
ua_node_types.opcua_node_variable_t.__historizing__
bool __historizing__
Definition: ua_node_types.py:927
ua_node_types.opcua_node_view_t.__init_subType__
def __init_subType__(self)
Definition: ua_node_types.py:1720
ua_node_types.opcua_node_method_t.__methodDecalaration__
__methodDecalaration__
Definition: ua_node_types.py:1119
ua_node_types.opcua_node_t.description
def description(self, data=None)
Definition: ua_node_types.py:439
ua_node_types.opcua_node_method_t
Definition: ua_node_types.py:1116
ua_node_types.opcua_node_t.id
def id(self)
Definition: ua_node_types.py:405
ua_node_types.opcua_node_variable_t.__dataType__
__dataType__
Definition: ua_node_types.py:921
ua_node_types.opcua_referencePointer_t.__cmp__
def __cmp__(self, other)
Definition: ua_node_types.py:148
ua_node_types.opcua_node_view_t.containsNoLoops
def containsNoLoops(self, data=None)
Definition: ua_node_types.py:1725
ua_node_types.opcua_node_variable_t.value
def value(self, data=0)
Definition: ua_node_types.py:941
ua_node_types.opcua_node_method_t.parseXMLSubType
def parseXMLSubType(self, xmlelement)
Definition: ua_node_types.py:1150
ua_node_types.opcua_referencePointer_t.__isForward__
bool __isForward__
Definition: ua_node_types.py:53
ua_node_types.opcua_node_variable_t.printOpen62541CCode_Subtype
def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping=True)
Definition: ua_node_types.py:1091
ua_node_types.getNextElementNode
def getNextElementNode(xmlvalue)
Definition: ua_node_types.py:31
ua_node_types.opcua_node_variable_t
Definition: ua_node_types.py:919
ua_node_types.opcua_node_variableType_t.dataType
def dataType(self, data=None)
Definition: ua_node_types.py:1269
ua_node_types.unicode
def unicode(s)
Definition: ua_node_types.py:916
ua_node_types.opcua_node_t.printOpen62541CCode
def printOpen62541CCode(self, unPrintedNodes=[], unPrintedReferences=[], supressGenerationOfAttribute=[])
Definition: ua_node_types.py:658
ua_node_types.opcua_node_t.FLAG_HISTORIZING
FLAG_HISTORIZING
Definition: ua_node_types.py:268
ua_node_types.opcua_node_t.nodeClass
def nodeClass(self, c=0)
Definition: ua_node_types.py:411
ua_node_types.opcua_referencePointer_t.isForward
def isForward(self, data=None)
Definition: ua_node_types.py:70
ua_node_types.opcua_referencePointer_t.parent
def parent(self)
Definition: ua_node_types.py:90
ua_node_types.opcua_node_t.getCodePrintableID
def getCodePrintableID(self)
Definition: ua_node_types.py:285
ua_node_types.opcua_node_t.__node_referencedBy__
list __node_referencedBy__
Definition: ua_node_types.py:247
ua_node_types.opcua_node_object_t
Definition: ua_node_types.py:854
ua_node_types.opcua_node_t.printDot
def printDot(self)
Definition: ua_node_types.py:491
ua_node_types.opcua_node_variable_t.sanitizeSubType
def sanitizeSubType(self)
Definition: ua_node_types.py:981
ua_node_types.opcua_node_t.__init__
def __init__(self, id, ns)
Definition: ua_node_types.py:251
ua_node_types.opcua_node_objectType_t.__init_subType__
def __init_subType__(self)
Definition: ua_node_types.py:1189
ua_node_types.opcua_node_t.FLAG_ISABSTRACT
FLAG_ISABSTRACT
Definition: ua_node_types.py:263
ua_node_types.opcua_node_objectType_t
Definition: ua_node_types.py:1186
ua_node_types.opcua_node_dataType_t.__encodingBuilt__
bool __encodingBuilt__
Definition: ua_node_types.py:1401
ua_node_types.opcua_referencePointer_t.__target__
__target__
Definition: ua_node_types.py:52
ua_node_types.opcua_node_dataType_t.__isAbstract__
bool __isAbstract__
Definition: ua_node_types.py:1396
ua_node_types.opcua_node_t.hasInverseReferenceTarget
def hasInverseReferenceTarget(self, node)
Definition: ua_node_types.py:345
ua_node_types.opcua_node_variable_t.printOpen62541CCode_SubtypeEarly
def printOpen62541CCode_SubtypeEarly(self, bootstrapping=True)
Definition: ua_node_types.py:1076
ua_node_types.opcua_node_t.__node_displayName__
string __node_displayName__
Definition: ua_node_types.py:241
ua_node_types.opcua_node_id_t.ns
int ns
Definition: ua_node_types.py:173
ua_node_types.opcua_node_referenceType_t
Definition: ua_node_types.py:747
ua_node_types.opcua_node_t.sanitize
def sanitize(self)
Definition: ua_node_types.py:506
ua_node_types.opcua_node_dataType_t
Definition: ua_node_types.py:1371
ua_node_types.opcua_node_t.initiateDummyXMLReferences
def initiateDummyXMLReferences(self, xmlelement)
Definition: ua_node_types.py:463
ua_node_types.opcua_node_variable_t.parseXMLSubType
def parseXMLSubType(self, xmlelement)
Definition: ua_node_types.py:1023
ua_node_types.opcua_node_variableType_t.printOpen62541CCode_SubtypeEarly
def printOpen62541CCode_SubtypeEarly(self, bootstrapping=True)
Definition: ua_node_types.py:1333
ua_node_types.opcua_node_t.removeReference
def removeReference(self, ref)
Definition: ua_node_types.py:309
ua_node_types.opcua_referencePointer_t.__reference_type__
__reference_type__
Definition: ua_node_types.py:51
ua_node_types.opcua_node_t.__repr__
def __repr__(self)
Definition: ua_node_types.py:279
ua_node_types.opcua_node_t.printOpen62541CCode_SubtypeEarly
def printOpen62541CCode_SubtypeEarly(self, bootstrapping=True)
Definition: ua_node_types.py:642
ua_node_types.opcua_node_referenceType_t.parseXMLSubType
def parseXMLSubType(self, xmlelement)
Definition: ua_node_types.py:787
ua_node_types.opcua_node_t.__node_class__
int __node_class__
Definition: ua_node_types.py:239
ua_node_types.opcua_referencePointer_t.__parentNode__
__parentNode__
Definition: ua_node_types.py:55
ua_node_types.opcua_node_variable_t.__userAccessLevel__
int __userAccessLevel__
Definition: ua_node_types.py:925
ua_node_types.opcua_node_method_t.methodDeclaration
def methodDeclaration(self, data=None)
Definition: ua_node_types.py:1127
ua_node_types.opcua_node_t.printOpen62541CCode_Subtype
def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping=True)
Definition: ua_node_types.py:650
ua_node_types.opcua_referencePointer_t.getCodePrintableID
def getCodePrintableID(self)
Definition: ua_node_types.py:93
ua_node_types.opcua_node_variableType_t.__dataType__
__dataType__
Definition: ua_node_types.py:1251
ua_node_types.opcua_node_method_t.__executable__
bool __executable__
Definition: ua_node_types.py:1117
ua_node_types.opcua_node_variable_t.__value__
int __value__
Definition: ua_node_types.py:920
ua_node_types.opcua_node_referenceType_t.__init_subType__
def __init_subType__(self)
Definition: ua_node_types.py:753
ua_node_types.opcua_node_t.__binary__
string __binary__
Definition: ua_node_types.py:248
ua_node_types.opcua_node_view_t
Definition: ua_node_types.py:1716
open62541_MacroHelper.open62541_MacroHelper
Definition: open62541_MacroHelper.py:34
ua_node_types.opcua_node_variableType_t.__isAbstract__
bool __isAbstract__
Definition: ua_node_types.py:1254
ua_node_types.opcua_node_object_t.__init_subType__
def __init_subType__(self)
Definition: ua_node_types.py:857
ua_node_types.opcua_referencePointer_t.__repr__
def __repr__(self)
Definition: ua_node_types.py:145
ua_builtin_types.opcua_value_t
Definition: ua_builtin_types.py:46
ua_node_types.opcua_node_referenceType_t.printOpen62541CCode_Subtype
def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping=True)
Definition: ua_node_types.py:814
ua_node_types.opcua_node_t.browseName
def browseName(self, data=0)
Definition: ua_node_types.py:421
ua_node_types.opcua_node_view_t.__eventNotifier__
int __eventNotifier__
Definition: ua_node_types.py:1718
ua_node_types.opcua_node_variable_t.__xmlValueDef__
__xmlValueDef__
Definition: ua_node_types.py:939
ua_node_types.opcua_node_t.parseXMLSubType
def parseXMLSubType(self, xmlelement)
Definition: ua_node_types.py:636
ua_node_types.opcua_node_view_t.parseXMLSubtype
def parseXMLSubtype(self, xmlelement)
Definition: ua_node_types.py:1735
ua_node_types.opcua_node_method_t.userExecutable
def userExecutable(self, data=None)
Definition: ua_node_types.py:1137
ua_node_types.opcua_node_object_t.eventNotifier
def eventNotifier(self, data="")
Definition: ua_node_types.py:861
str
#define str(a)
Definition: ua_adapter.cpp:52
ua_node_types.opcua_node_referenceType_t.__reference_referenceType__
__reference_referenceType__
Definition: ua_node_types.py:751
ua_node_types.opcua_node_variableType_t.__valueRank__
int __valueRank__
Definition: ua_node_types.py:1252
ua_node_types.opcua_node_method_t.executable
def executable(self, data=None)
Definition: ua_node_types.py:1132
ua_node_types.opcua_node_variableType_t.__init_subType__
def __init_subType__(self)
Definition: ua_node_types.py:1257
ua_node_types.opcua_node_variableType_t.valueRank
def valueRank(self, data=None)
Definition: ua_node_types.py:1274
ua_node_types.opcua_node_variableType_t.arrayDimensions
def arrayDimensions(self, data=None)
Definition: ua_node_types.py:1279
ua_node_types.opcua_node_referenceType_t.__reference_inverseName__
string __reference_inverseName__
Definition: ua_node_types.py:750
ua_node_types.opcua_node_t.__node_browseName__
string __node_browseName__
Definition: ua_node_types.py:240
ua_node_types.opcua_node_referenceType_t.__isAbstract__
bool __isAbstract__
Definition: ua_node_types.py:748
ua_node_types.opcua_node_referenceType_t.__reference_symmetric__
__reference_symmetric__
Definition: ua_node_types.py:756
ua_node_types.opcua_node_variable_t.__init_subType__
def __init_subType__(self)
Definition: ua_node_types.py:929
ua_node_types.opcua_node_t.__node_description__
string __node_description__
Definition: ua_node_types.py:242
ua_node_types.opcua_node_view_t.__containsNoLoops__
bool __containsNoLoops__
Definition: ua_node_types.py:1717
ua_node_types.opcua_node_referenceType_t.__symmetric__
bool __symmetric__
Definition: ua_node_types.py:749
ua_node_types.opcua_node_t.FLAG_CONTAINSNOLOOPS
FLAG_CONTAINSNOLOOPS
Definition: ua_node_types.py:265
ua_node_types.opcua_node_variable_t.__arrayDimensions__
int __arrayDimensions__
Definition: ua_node_types.py:923
ua_node_types.opcua_referencePointer_t.__isHidden__
__isHidden__
Definition: ua_node_types.py:61
ua_node_types.opcua_node_variable_t.arrayDimensions
def arrayDimensions(self, data=None)
Definition: ua_node_types.py:956
ua_node_types.opcua_node_variable_t.historizing
def historizing(self, data=None)
Definition: ua_node_types.py:976
ua_node_types.opcua_node_variableType_t.printOpen62541CCode_Subtype
def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping=True)
Definition: ua_node_types.py:1348
ua_node_types.opcua_node_t.addInverseReferenceTarget
def addInverseReferenceTarget(self, node)
Definition: ua_node_types.py:320
ua_node_types.opcua_node_dataType_t.isAbstract
def isAbstract(self, data=None)
Definition: ua_node_types.py:1414
ua_node_types.opcua_node_t.FLAG_USEREXECUTABLE
FLAG_USEREXECUTABLE
Definition: ua_node_types.py:267
ua_node_types.opcua_node_variable_t.userAccessLevel
def userAccessLevel(self, data=None)
Definition: ua_node_types.py:966
ua_node_types.opcua_node_t
Definition: ua_node_types.py:237
ua_node_types.opcua_node_id_t.g
string g
Definition: ua_node_types.py:171
ua_node_types.opcua_node_dataType_t.__definition__
list __definition__
Definition: ua_node_types.py:1402
ua_node_types.opcua_node_t.__node_userWriteMask__
int __node_userWriteMask__
Definition: ua_node_types.py:244
ua_node_types.opcua_node_t.printXML
def printXML(self)
Definition: ua_node_types.py:639
ua_node_types.opcua_node_dataType_t.__baseTypeEncoding__
list __baseTypeEncoding__
Definition: ua_node_types.py:1399
ua_node_types.opcua_node_referenceType_t.isAbstract
def isAbstract(self, data=None)
Definition: ua_node_types.py:765
ua_node_types.opcua_node_dataType_t.__isEnum__
bool __isEnum__
Definition: ua_node_types.py:1397
ua_node_types.opcua_node_t.userWriteMask
def userWriteMask(self, data=None)
Definition: ua_node_types.py:455
ua_node_types.opcua_node_variableType_t.__xmlDefinition__
__xmlDefinition__
Definition: ua_node_types.py:1255
ua_node_types.opcua_node_t.FLAG_SYMMETRIC
FLAG_SYMMETRIC
Definition: ua_node_types.py:264
ua_node_types.opcua_node_id_t.__mystrname__
string __mystrname__
Definition: ua_node_types.py:174
ua_node_types.opcua_node_variableType_t.sanitizeSubType
def sanitizeSubType(self)
Definition: ua_node_types.py:1289
ua_node_types.opcua_node_id_t.i
int i
Definition: ua_node_types.py:169
ua_node_types.opcua_node_variableType_t.__value__
int __value__
Definition: ua_node_types.py:1250
ua_node_types.opcua_node_id_t.__init__
def __init__(self, idstring)
Definition: ua_node_types.py:176
ua_node_types.opcua_node_dataType_t.encodedTypeId
def encodedTypeId(self)
Definition: ua_node_types.py:1650
ua_node_types.opcua_node_t.getReferences
def getReferences(self)
Definition: ua_node_types.py:339
ua_node_types.opcua_node_id_t.b
b
Definition: ua_node_types.py:179
ua_node_types.opcua_node_variable_t.allocateValue
def allocateValue(self)
Definition: ua_node_types.py:993
ua_node_types.opcua_referencePointer_t.target
def target(self, data=None)
Definition: ua_node_types.py:80
ua_node_types.opcua_node_object_t.parseXMLSubType
def parseXMLSubType(self, xmlelement)
Definition: ua_node_types.py:866
ua_node_types.opcua_node_id_t.__str__
def __str__(self)
Definition: ua_node_types.py:222
ua_node_types.opcua_node_t.__node_id__
__node_id__
Definition: ua_node_types.py:238
ua_node_types.opcua_referencePointer_t.__addr__
int __addr__
Definition: ua_node_types.py:54
ua_node_types.opcua_referencePointer_t.isHidden
def isHidden(self, data=None)
Definition: ua_node_types.py:65
ua_node_types.opcua_node_objectType_t.__isAbstract__
bool __isAbstract__
Definition: ua_node_types.py:1187
ua_node_types.opcua_node_dataType_t.__encodable__
bool __encodable__
Definition: ua_node_types.py:1400
ua_node_types.opcua_node_t.getInverseReferences
def getInverseReferences(self)
Definition: ua_node_types.py:342
ua_node_types.opcua_node_id_t.toString
def toString(self)
Definition: ua_node_types.py:202
ua_node_types.opcua_node_method_t.__init_subType__
def __init_subType__(self)
Definition: ua_node_types.py:1121
ua_node_types.opcua_node_t.writeMask
def writeMask(self, data=None)
Definition: ua_node_types.py:447
ua_node_types.opcua_node_variable_t.__accessLevel__
int __accessLevel__
Definition: ua_node_types.py:924
ua_node_types.opcua_node_t.__str__
def __str__(self)
Definition: ua_node_types.py:274
ua_node_types.opcua_node_dataType_t.getEncoding
def getEncoding(self)
Definition: ua_node_types.py:1433
ua_node_types.opcua_node_t.__node_namespace__
__node_namespace__
Definition: ua_node_types.py:245
ua_node_types.opcua_node_method_t.__userExecutable__
bool __userExecutable__
Definition: ua_node_types.py:1118
ua_node_types.opcua_node_variableType_t
Definition: ua_node_types.py:1249
ua_node_types.opcua_node_referenceType_t.referenceType
def referenceType(self, data=None)
Definition: ua_node_types.py:760
ua_node_types.opcua_node_variableType_t.isAbstract
def isAbstract(self, data=None)
Definition: ua_node_types.py:1284
ua_node_types.opcua_node_object_t.printOpen62541CCode_Subtype
def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping=True)
Definition: ua_node_types.py:881
ua_node_types.opcua_node_t.removeReferenceToNode
def removeReferenceToNode(self, targetNode)
Definition: ua_node_types.py:313
ua_node_types.opcua_node_t.getFirstParentNode
def getFirstParentNode(self)
Definition: ua_node_types.py:357
ua_node_types.opcua_node_t.addReference
def addReference(self, ref)
Definition: ua_node_types.py:302
ua_node_types.opcua_node_id_t.s
string s
Definition: ua_node_types.py:172
ua_node_types.opcua_node_dataType_t.__init_subType__
def __init_subType__(self)
Definition: ua_node_types.py:1404
ua_node_types.opcua_node_variable_t.dataType
def dataType(self, data=None)
Definition: ua_node_types.py:946
ua_node_types.opcua_node_id_t.__repr__
def __repr__(self)
Definition: ua_node_types.py:230
ua_node_types.opcua_node_variable_t.accessLevel
def accessLevel(self, data=None)
Definition: ua_node_types.py:961
ua_node_types.opcua_node_view_t.printOpen62541CCode_Subtype
def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping=True)
Definition: ua_node_types.py:1743
ua_node_types.opcua_node_referenceType_t.symmetric
def symmetric(self, data=None)
Definition: ua_node_types.py:770
ua_node_types.opcua_node_objectType_t.parseXMLSubType
def parseXMLSubType(self, xmlelement)
Definition: ua_node_types.py:1198
ua_node_types.opcua_node_method_t.printOpen62541CCode_Subtype
def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping=True)
Definition: ua_node_types.py:1163
ua_node_types.opcua_node_t.__init_subType__
def __init_subType__(self)
Definition: ua_node_types.py:271
ua_node_types.opcua_node_t.parseXML
def parseXML(self, xmlelement)
Definition: ua_node_types.py:570
ua_node_types.opcua_node_objectType_t.isAbstract
def isAbstract(self, data=None)
Definition: ua_node_types.py:1193
ua_node_types.opcua_node_variable_t.valueRank
def valueRank(self, data="")
Definition: ua_node_types.py:951
ua_node_types.opcua_node_referenceType_t.sanitizeSubType
def sanitizeSubType(self)
Definition: ua_node_types.py:780
ua_node_types.opcua_referencePointer_t.referenceType
def referenceType(self, type=None)
Definition: ua_node_types.py:75
ua_node_types.opcua_node_object_t.__object_eventNotifier__
int __object_eventNotifier__
Definition: ua_node_types.py:855
ua_node_types.opcua_node_variable_t.__minimumSamplingInterval__
int __minimumSamplingInterval__
Definition: ua_node_types.py:926
ua_node_types.opcua_node_view_t.eventNotifier
def eventNotifier(self, data=None)
Definition: ua_node_types.py:1730
ua_node_types.opcua_node_t.sanitizeSubType
def sanitizeSubType(self)
Definition: ua_node_types.py:555
ua_node_types.opcua_node_dataType_t.buildEncoding
def buildEncoding(self, indent=0, force=False)
Definition: ua_node_types.py:1449
ua_node_types.opcua_referencePointer_t.__str__
def __str__(self)
Definition: ua_node_types.py:113
ua_node_types.opcua_node_variable_t.minimumSamplingInterval
def minimumSamplingInterval(self, data=None)
Definition: ua_node_types.py:971
generate_open62541CCode.id
id
Definition: generate_open62541CCode.py:127
ua_node_types.opcua_node_dataType_t.parseXMLSubType
def parseXMLSubType(self, xmlelement)
Definition: ua_node_types.py:1626
ua_node_types.opcua_node_referenceType_t.inverseName
def inverseName(self, data=None)
Definition: ua_node_types.py:775
ua_node_types.opcua_referencePointer_t.__init__
def __init__(self, target, hidden=False, parentNode=None)
Definition: ua_node_types.py:57
ua_node_types.opcua_node_t.displayName
def displayName(self, data=None)
Definition: ua_node_types.py:431
ua_node_types.opcua_node_variableType_t.parseXMLSubType
def parseXMLSubType(self, xmlelement)
Definition: ua_node_types.py:1305
ua_node_types.opcua_node_variableType_t.__arrayDimensions__
int __arrayDimensions__
Definition: ua_node_types.py:1253
ua_node_types.opcua_node_variableType_t.value
def value(self, data=None)
Definition: ua_node_types.py:1266
ua_node_types.opcua_node_method_t.sanitizeSubType
def sanitizeSubType(self)
Definition: ua_node_types.py:1142
ua_node_types.opcua_node_t.getNamespace
def getNamespace(self)
Definition: ua_node_types.py:408
ua_node_types.opcua_node_id_t
Definition: ua_node_types.py:162
ua_node_types.opcua_node_t.__node_references__
list __node_references__
Definition: ua_node_types.py:246
ua_node_types.opcua_node_t.FLAG_EXECUTABLE
FLAG_EXECUTABLE
Definition: ua_node_types.py:266
ua_node_types.opcua_node_dataType_t.__xmlDefinition__
__xmlDefinition__
Definition: ua_node_types.py:1398
ua_node_types.opcua_node_variable_t.__valueRank__
int __valueRank__
Definition: ua_node_types.py:922
ua_node_types.opcua_referencePointer_t
References are not really described by OPC-UA.
Definition: ua_node_types.py:44
ua_node_types.opcua_node_t.address
def address(self, addr=None)
Definition: ua_node_types.py:558
ua_node_types.opcua_node_dataType_t.isEncodable
def isEncodable(self)
Definition: ua_node_types.py:1424
ua_node_types.opcua_node_id_t.__eq__
def __eq__(self, nodeId2)
Definition: ua_node_types.py:225
ua_node_types.opcua_node_objectType_t.printOpen62541CCode_Subtype
def printOpen62541CCode_Subtype(self, unPrintedReferences=[], bootstrapping=True)
Definition: ua_node_types.py:1211
ua_node_types.opcua_node_t.updateInverseReferences
def updateInverseReferences(self)
Definition: ua_node_types.py:387
ua_builtin_types.opcua_BuiltinType_extensionObject_t
Definition: ua_builtin_types.py:424
ua_node_types.opcua_referencePointer_t.address
def address(self, data=None)
Definition: ua_node_types.py:85