123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717 |
- #!/usr/bin/env/python
- # -*- coding: utf-8 -*-
- ###
- ### Author: Chris Iatrou (ichrispa@core-vector.net)
- ### Version: rev 13
- ###
- ### This program was created for educational purposes and has been
- ### contributed to the open62541 project by the author. All licensing
- ### terms for this source is inherited by the terms and conditions
- ### specified for by the open62541 project (see the projects readme
- ### file for more information on the LGPL terms and restrictions).
- ###
- ### This program is not meant to be used in a production environment. The
- ### author is not liable for any complications arising due to the use of
- ### this program.
- ###
- from ua_node_types import *
- ####################
- # Helper Functions #
- ####################
- def getCreateNodeIDMacro(node):
- if node.id().i != None:
- return "UA_NODEID_NUMERIC(%s, %s)" % (node.id().ns, node.id().i)
- elif node.id().s != None:
- return "UA_NODEID_STRING(%s, %s)" % (node.id().ns, node.id().s)
- elif node.id().b != None:
- logger.debug("NodeID Generation macro for bytestrings has not been implemented.")
- return ""
- elif node.id().g != None:
- logger.debug("NodeID Generation macro for guids has not been implemented.")
- return ""
- else:
- return ""
- def getCreateExpandedNodeIDMacro(node):
- if node.id().i != None:
- return "UA_EXPANDEDNODEID_NUMERIC(%s, %s)" % (str(node.id().ns),str(node.id().i))
- elif node.id().s != None:
- return "UA_EXPANDEDNODEID_STRING(%s, %s)" % (str(node.id().ns), node.id().s)
- elif node.id().b != None:
- logger.debug("NodeID Generation macro for bytestrings has not been implemented.")
- return ""
- elif node.id().g != None:
- logger.debug("NodeID Generation macro for guids has not been implemented.")
- return ""
- else:
- return ""
- def getCreateStandaloneReference(sourcenode, reference):
- code = []
- if reference.isForward():
- code.append("UA_Server_addReference(server, %s, %s, %s, true);" % \
- (getCreateNodeIDMacro(sourcenode), getCreateNodeIDMacro(reference.referenceType()), \
- getCreateExpandedNodeIDMacro(reference.target())))
- else:
- code.append("UA_Server_addReference(server, %s, %s, %s, false);" % \
- (getCreateNodeIDMacro(sourcenode), getCreateNodeIDMacro(reference.referenceType()), \
- getCreateExpandedNodeIDMacro(reference.target())))
- return code
- #################
- # Subtype Early #
- #################
- def Node_printOpen62541CCode_SubtypeEarly(node, bootstrapping = True):
- """ Initiate code segments for the nodes instantiotion that preceed
- the actual UA_Server_addNode or UA_NodeStore_insert calls.
- """
- code = []
- if isinstance(node, opcua_node_variable_t) or isinstance(node, opcua_node_variableType_t):
- # If we have an encodable value, try to encode that
- if node.dataType() != None and isinstance(node.dataType().target(), opcua_node_dataType_t):
- # Delegate the encoding of the datavalue to the helper if we have
- # determined a valid encoding
- if node.dataType().target().isEncodable():
- if node.value() != None:
- code.extend(node.value().printOpen62541CCode(bootstrapping))
- return code
- if(bootstrapping):
- code.append("UA_Variant *" + node.getCodePrintableID() + "_variant = UA_alloca(sizeof(UA_Variant));")
- code.append("UA_Variant_init(" + node.getCodePrintableID() + "_variant);")
- return code
- ###########
- # Subtype #
- ###########
- def ReferenceTypeNode_printOpen62541CCode_Subtype(node, unPrintedReferences=[], bootstrapping = True):
- code = []
- # Detect if this is bootstrapping or if we are attempting to use userspace...
- if bootstrapping == False:
- typeDefs = node.getNamespace().getSubTypesOf() # defaults to TypeDefinition
- myTypeRef = None
- for ref in node.getReferences():
- if ref.referenceType() in typeDefs:
- myTypeRef = ref
- break
- if myTypeRef==None:
- for ref in node.getReferences():
- if ref.referenceType().browseName() == "HasSubtype" and ref.isForward() == False:
- myTypeRef = ref
- break
- if myTypeRef==None:
- logger.warn(str(self) + " failed to locate a type definition, assuming BaseDataType.")
- code.append(" // No valid typeDefinition found; assuming BaseDataType")
- code.append(" UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE),")
- else:
- code.append(" " + getCreateExpandedNodeIDMacro(myTypeRef.target()) + ",")
- while myTypeRef in unPrintedReferences:
- unPrintedReferences.remove(myTypeRef)
- code.append(" UA_LOCALIZEDTEXT(\"\",\"" + str(node.inverseName()) + "\"),");
- code.append(" // FIXME: Missing, isAbstract")
- code.append(" // FIXME: Missing, symmetric")
- return code
- if node.isAbstract():
- code.append(node.getCodePrintableID() + "->isAbstract = true;")
- if node.symmetric():
- code.append(node.getCodePrintableID() + "->symmetric = true;")
- if node.__reference_inverseName__ != "":
- code.append(node.getCodePrintableID() + "->inverseName = UA_LOCALIZEDTEXT_ALLOC(\"en_US\", \"" + \
- node.__reference_inverseName__ + "\");")
- return code;
- def ObjectNode_printOpen62541CCode_Subtype(node, unPrintedReferences=[], bootstrapping = True):
- code = []
- # Detect if this is bootstrapping or if we are attempting to use userspace...
- if bootstrapping == False:
- typeDefs = self.getNamespace().getSubTypesOf() # defaults to TypeDefinition
- myTypeRef = None
- for ref in self.getReferences():
- if ref.referenceType() in typeDefs:
- myTypeRef = ref
- break
- if myTypeRef==None:
- for ref in self.getReferences():
- if ref.referenceType().browseName() == "HasSubtype" and ref.isForward() == False:
- myTypeRef = ref
- break
- if myTypeRef==None:
- logger.warn(str(self) + " failed to locate a type definition, assuming BaseObjectType.")
- code.append(" // No valid typeDefinition found; assuming BaseObjectType")
- code.append(" UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),")
- else:
- code.append(" " + getCreateExpandedNodeIDMacro(myTypeRef.target()) + ",")
- while myTypeRef in unPrintedReferences:
- unPrintedReferences.remove(myTypeRef)
- #FIXME: No event notifier in UA_Server_addNode call!
- return code
- # We are being bootstrapped! Add the raw attributes to the node.
- code.append(node.getCodePrintableID() + "->eventNotifier = (UA_Byte) " + str(node.eventNotifier()) + ";")
- return code
- def ObjectTypeNode_printOpen62541CCode_Subtype(node, unPrintedReferences=[], bootstrapping = True):
- code = []
- # Detect if this is bootstrapping or if we are attempting to use userspace...
- if bootstrapping == False:
- typeDefs = node.getNamespace().getSubTypesOf() # defaults to TypeDefinition
- myTypeRef = None
- for ref in node.getReferences():
- if ref.referenceType() in typeDefs:
- myTypeRef = ref
- break
- if myTypeRef==None:
- for ref in node.getReferences():
- if ref.referenceType().browseName() == "HasSubtype" and ref.isForward() == False:
- myTypeRef = ref
- break
- if myTypeRef==None:
- logger.warn(str(node) + " failed to locate a type definition, assuming BaseObjectType.")
- code.append(" // No valid typeDefinition found; assuming BaseObjectType")
- code.append(" UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),")
- else:
- code.append(" " + getCreateExpandedNodeIDMacro(myTypeRef.target()) + ",")
- while myTypeRef in unPrintedReferences:
- code.append(" // removed " + str(myTypeRef))
- unPrintedReferences.remove(myTypeRef)
- if (node.isAbstract()):
- code.append(" true,")
- else:
- code.append(" false,")
- # Fallback mode for bootstrapping
- if (node.isAbstract()):
- code.append(node.getCodePrintableID() + "->isAbstract = true;")
- return code
- def VariableNode_printOpen62541CCode_Subtype(node, unPrintedReferences=[], bootstrapping = True):
- code = []
- # Detect if this is bootstrapping or if we are attempting to use userspace...
- if bootstrapping == False:
- code.append(" " + node.getCodePrintableID() + "_variant, ")
- code.append(" // FIXME: missing minimumSamplingInterval")
- code.append(" // FIXME: missing accessLevel")
- code.append(" // FIXME: missing userAccessLevel")
- code.append(" // FIXME: missing valueRank")
- return code
- if node.historizing():
- code.append(node.getCodePrintableID() + "->historizing = true;")
- code.append(node.getCodePrintableID() + "->minimumSamplingInterval = (UA_Double) " + \
- str(node.minimumSamplingInterval()) + ";")
- code.append(node.getCodePrintableID() + "->userAccessLevel = (UA_Int32) " + str(node.userAccessLevel()) + ";")
- code.append(node.getCodePrintableID() + "->accessLevel = (UA_Int32) " + str(node.accessLevel()) + ";")
- code.append(node.getCodePrintableID() + "->valueRank = (UA_Int32) " + str(node.valueRank()) + ";")
- # The variant is guaranteed to exist by SubtypeEarly()
- code.append(node.getCodePrintableID() + "->value.variant.value = *" + node.getCodePrintableID() + "_variant;")
- code.append(node.getCodePrintableID() + "->valueSource = UA_VALUESOURCE_VARIANT;")
- return code
- def VariableTypeNode_printOpen62541CCode_Subtype(node, unPrintedReferences=[], bootstrapping = True):
- code = []
- if bootstrapping == False:
- code.append(" " + node.getCodePrintableID() + "_variant, ")
- code.append(" " + str(node.valueRank()) + ",")
- if node.isAbstract():
- code.append(" true,")
- else:
- code.append(" false,")
- return code
- if (node.isAbstract()):
- code.append(node.getCodePrintableID() + "->isAbstract = true;")
- else:
- code.append(node.getCodePrintableID() + "->isAbstract = false;")
- # The variant is guaranteed to exist by SubtypeEarly()
- code.append(node.getCodePrintableID() + "->value.variant.value = *" + node.getCodePrintableID() + "_variant;")
- code.append(node.getCodePrintableID() + "->valueSource = UA_VALUESOURCE_VARIANT;")
- return code
- def MethodNode_printOpen62541CCode_Subtype(node, unPrintedReferences=[], bootstrapping = True):
- code = []
- # Detect if this is bootstrapping or if we are attempting to use userspace...
- if bootstrapping == False:
- code.append(" // Note: in/outputArguments are added by attaching the variable nodes,")
- code.append(" // not by including the in the addMethodNode() call.")
- code.append(" NULL,")
- code.append(" NULL,")
- code.append(" 0, NULL,")
- code.append(" 0, NULL,")
- code.append(" // FIXME: Missing executable")
- code.append(" // FIXME: Missing userExecutable")
- return code
- # UA_False is default for booleans on _init()
- if node.executable():
- code.append(node.getCodePrintableID() + "->executable = true;")
- if node.userExecutable():
- code.append(node.getCodePrintableID() + "->userExecutable = true;")
- return code
- def DataTypeNode_printOpen62541CCode_Subtype(node, unPrintedReferences=[], bootstrapping = True):
- code = []
- # Detect if this is bootstrapping or if we are attempting to use userspace...
- if bootstrapping == False:
- typeDefs = node.getNamespace().getSubTypesOf() # defaults to TypeDefinition
- myTypeRef = None
- for ref in node.getReferences():
- if ref.referenceType() in typeDefs:
- myTypeRef = ref
- break
- if myTypeRef==None:
- for ref in node.getReferences():
- if ref.referenceType().browseName() == "HasSubtype" and ref.isForward() == False:
- myTypeRef = ref
- break
- if myTypeRef==None:
- logger.warn(str(node) + " failed to locate a type definition, assuming BaseDataType.")
- code.append(" // No valid typeDefinition found; assuming BaseDataType")
- code.append(" UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE),")
- else:
- code.append(" " + getCreateExpandedNodeIDMacro(myTypeRef.target()) + ",")
- while myTypeRef in unPrintedReferences:
- unPrintedReferences.remove(myTypeRef)
- if (node.isAbstract()):
- code.append(" true,")
- else:
- code.append(" false,")
- return code
- if (node.isAbstract()):
- code.append(node.getCodePrintableID() + "->isAbstract = true;")
- else:
- code.append(node.getCodePrintableID() + "->isAbstract = false;")
- return code
- def ViewNode_printOpen62541CCode_Subtype(node, unPrintedReferences=[], bootstrapping = True):
- code = []
- # Detect if this is bootstrapping or if we are attempting to use userspace...
- if bootstrapping == False:
- typeDefs = node.getNamespace().getSubTypesOf() # defaults to TypeDefinition
- myTypeRef = None
- for ref in node.getReferences():
- if ref.referenceType() in typeDefs:
- myTypeRef = ref
- break
- if myTypeRef==None:
- for ref in node.getReferences():
- if ref.referenceType().browseName() == "HasSubtype" and ref.isForward() == False:
- myTypeRef = ref
- break
- if myTypeRef==None:
- logger.warn(str(node) + " failed to locate a type definition, assuming BaseViewType.")
- code.append(" // No valid typeDefinition found; assuming BaseViewType")
- code.append(" UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEViewTYPE),")
- else:
- code.append(" " + getCreateExpandedNodeIDMacro(myTypeRef.target()) + ",")
- while myTypeRef in unPrintedReferences:
- unPrintedReferences.remove(myTypeRef)
- code.append(" // FIXME: Missing eventNotifier")
- code.append(" // FIXME: Missing containsNoLoops")
- return code
- if node.containsNoLoops():
- code.append(node.getCodePrintableID() + "->containsNoLoops = true;")
- else:
- code.append(node.getCodePrintableID() + "->containsNoLoops = false;")
- code.append(node.getCodePrintableID() + "->eventNotifier = (UA_Byte) " + str(node.eventNotifier()) + ";")
- return code
- def Node_printOpen62541CCode_Subtype(node, unPrintedReferences=[], bootstrapping = True):
- """ Appends node type specific information to the nodes UA_Server_addNode
- or UA_NodeStore_insert calls.
- """
- if isinstance(node, opcua_node_referenceType_t):
- return ReferenceTypeNode_printOpen62541CCode_Subtype(node, unPrintedReferences, bootstrapping)
- elif isinstance(node, opcua_node_object_t):
- return ObjectNode_printOpen62541CCode_Subtype(node, unPrintedReferences, bootstrapping)
- elif isinstance(node, opcua_node_objectType_t):
- return ObjectTypeNode_printOpen62541CCode_Subtype(node, unPrintedReferences, bootstrapping)
- elif isinstance(node, opcua_node_variable_t):
- return VariableNode_printOpen62541CCode_Subtype(node, unPrintedReferences, bootstrapping)
- elif isinstance(node, opcua_node_variableType_t):
- return VariableTypeNode_printOpen62541CCode_Subtype(node, unPrintedReferences, bootstrapping)
- elif isinstance(node, opcua_node_method_t):
- return MethodNode_printOpen62541CCode_Subtype(node, unPrintedReferences, bootstrapping)
- elif isinstance(node, opcua_node_dataType_t):
- return DataTypeNode_printOpen62541CCode_Subtype(node, unPrintedReferences, bootstrapping)
- elif isinstance(node, opcua_node_view_t):
- return ViewNode_printOpen62541CCode_Subtype(node, unPrintedReferences, bootstrapping)
-
- raise Exception('Unknown node type', node)
- ###############
- # Entry Point #
- ###############
- def getCreateNodeNoBootstrap(node, parentNode, parentReference, unprintedNodes=[]):
- code = []
- code.append("// Node: %s, %s" % (str(node), str(node.browseName())))
- if node.nodeClass() == NODE_CLASS_OBJECT:
- nodetype = "Object"
- elif node.nodeClass() == NODE_CLASS_VARIABLE:
- nodetype = "Variable"
- elif node.nodeClass() == NODE_CLASS_METHOD:
- nodetype = "Method"
- elif node.nodeClass() == NODE_CLASS_OBJECTTYPE:
- nodetype = "ObjectType"
- elif node.nodeClass() == NODE_CLASS_REFERENCETYPE:
- nodetype = "ReferenceType"
- elif node.nodeClass() == NODE_CLASS_VARIABLETYPE:
- nodetype = "VariableType"
- elif node.nodeClass() == NODE_CLASS_DATATYPE:
- nodetype = "DataType"
- elif node.nodeClass() == NODE_CLASS_VIEW:
- nodetype = "View"
- else:
- code.append("/* undefined nodeclass */")
- return code;
- # If this is a method, construct in/outargs for addMethod
- #inputArguments.arrayDimensionsSize = 0;
- #inputArguments.arrayDimensions = NULL;
- #inputArguments.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
- # Node ordering should have made sure that arguments, if they exist, have not been printed yet
- if node.nodeClass() == NODE_CLASS_METHOD:
- inArgVal = []
- outArgVal = []
- code.append("UA_Argument *inputArguments = NULL;")
- code.append("UA_Argument *outputArguments = NULL;")
- for r in node.getReferences():
- if r.isForward():
- if r.target() != None and r.target().nodeClass() == NODE_CLASS_VARIABLE and \
- r.target().browseName() == 'InputArguments':
- while r.target() in unprintedNodes:
- unprintedNodes.remove(r.target())
- if r.target().value() != None:
- inArgVal = r.target().value().value
- elif r.target() != None and r.target().nodeClass() == NODE_CLASS_VARIABLE and \
- r.target().browseName() == 'OutputArguments':
- while r.target() in unprintedNodes:
- unprintedNodes.remove(r.target())
- if r.target().value() != None:
- outArgVal = r.target().value().value
- if len(inArgVal)>0:
- code.append("")
- code.append("inputArguments = (UA_Argument *) malloc(sizeof(UA_Argument) * " + \
- str(len(inArgVal)) + ");")
- code.append("int inputArgumentCnt;")
- code.append("for (inputArgumentCnt=0; inputArgumentCnt<" + str(len(inArgVal)) + \
- "; inputArgumentCnt++) UA_Argument_init(&inputArguments[inputArgumentCnt]); ")
- argumentCnt = 0
- for inArg in inArgVal:
- if inArg.getValueFieldByAlias("Description") != None:
- code.append("inputArguments[" + str(argumentCnt) + "].description = UA_LOCALIZEDTEXT(\"" + \
- str(inArg.getValueFieldByAlias("Description")[0]) + "\",\"" + \
- str(inArg.getValueFieldByAlias("Description")[1]) + "\");")
- if inArg.getValueFieldByAlias("Name") != None:
- code.append("inputArguments[" + str(argumentCnt) + "].name = UA_STRING(\"" + \
- str(inArg.getValueFieldByAlias("Name")) + "\");")
- if inArg.getValueFieldByAlias("ValueRank") != None:
- code.append("inputArguments[" + str(argumentCnt) + "].valueRank = " + \
- str(inArg.getValueFieldByAlias("ValueRank")) + ";")
- if inArg.getValueFieldByAlias("DataType") != None:
- code.append("inputArguments[" + str(argumentCnt) + "].dataType = " + \
- str(getCreateNodeIDMacro(inArg.getValueFieldByAlias("DataType"))) + ";")
- #if inArg.getValueFieldByAlias("ArrayDimensions") != None:
- # code.append("inputArguments[" + str(argumentCnt) + "].arrayDimensions = " + \
- # str(inArg.getValueFieldByAlias("ArrayDimensions")) + ";")
- argumentCnt += 1
- if len(outArgVal)>0:
- code.append("")
- code.append("outputArguments = (UA_Argument *) malloc(sizeof(UA_Argument) * " + \
- str(len(outArgVal)) + ");")
- code.append("int outputArgumentCnt;")
- code.append("for (outputArgumentCnt=0; outputArgumentCnt<" + str(len(outArgVal)) + \
- "; outputArgumentCnt++) UA_Argument_init(&outputArguments[outputArgumentCnt]); ")
- argumentCnt = 0
- for outArg in outArgVal:
- if outArg.getValueFieldByAlias("Description") != None:
- code.append("outputArguments[" + str(argumentCnt) + "].description = UA_LOCALIZEDTEXT(\"" + \
- str(outArg.getValueFieldByAlias("Description")[0]) + "\",\"" + \
- str(outArg.getValueFieldByAlias("Description")[1]) + "\");")
- if outArg.getValueFieldByAlias("Name") != None:
- code.append("outputArguments[" + str(argumentCnt) + "].name = UA_STRING(\"" + \
- str(outArg.getValueFieldByAlias("Name")) + "\");")
- if outArg.getValueFieldByAlias("ValueRank") != None:
- code.append("outputArguments[" + str(argumentCnt) + "].valueRank = " + \
- str(outArg.getValueFieldByAlias("ValueRank")) + ";")
- if outArg.getValueFieldByAlias("DataType") != None:
- code.append("outputArguments[" + str(argumentCnt) + "].dataType = " + \
- str(getCreateNodeIDMacro(outArg.getValueFieldByAlias("DataType"))) + ";")
- #if outArg.getValueFieldByAlias("ArrayDimensions") != None:
- # code.append("outputArguments[" + str(argumentCnt) + "].arrayDimensions = " + \
- # str(outArg.getValueFieldByAlias("ArrayDimensions")) + ";")
- argumentCnt += 1
- # print the attributes struct
- code.append("UA_%sAttributes attr;" % nodetype)
- code.append("UA_%sAttributes_init(&attr);" % nodetype);
- code.append("attr.displayName = UA_LOCALIZEDTEXT(\"\", \"%s\");" % node.displayName().replace("\"", "\\\""))
- code.append("attr.description = UA_LOCALIZEDTEXT(\"\", \"%s\");" % node.description().replace("\"", "\\\""))
- if nodetype == "Variable":
- code.append("attr.accessLevel = %s;" % str(node.accessLevel()))
- code.append("attr.userAccessLevel = %s;" % str(node.userAccessLevel()))
- if nodetype in ["Variable", "VariableType"]:
- code.extend(Node_printOpen62541CCode_SubtypeEarly(node, bootstrapping = False))
- elif nodetype == "Method":
- if node.executable():
- code.append("attr.executable = true;")
- if node.userExecutable():
- code.append("attr.userExecutable = true;")
- code.append("UA_NodeId nodeId = %s;" % str(getCreateNodeIDMacro(node)))
- if nodetype in ["Object", "Variable"]:
- #due to the current API we cannot set types here since the API will
- #generate nodes with random IDs
- code.append("UA_NodeId typeDefinition = UA_NODEID_NULL;")
- code.append("UA_NodeId parentNodeId = %s;" % str(getCreateNodeIDMacro(parentNode)))
- code.append("UA_NodeId parentReferenceNodeId = %s;" % \
- str(getCreateNodeIDMacro(parentReference.referenceType())))
- extrNs = node.browseName().split(":")
- if len(extrNs) > 1:
- code.append("UA_QualifiedName nodeName = UA_QUALIFIEDNAME(%s, \"%s\");" % (str(extrNs[0]), extrNs[1]))
- else:
- code.append("UA_QualifiedName nodeName = UA_QUALIFIEDNAME(0, \"%s\");" % str(node.browseName()))
- # In case of a MethodNode: Add in|outArg struct generation here. Mandates
- # that namespace reordering was done using Djikstra (check that arguments
- # have not been printed). (@ichrispa)
- code.append("UA_Server_add%sNode(server, nodeId, parentNodeId, parentReferenceNodeId, nodeName" % nodetype)
- if nodetype in ["Object", "Variable"]:
- code.append(" , typeDefinition")
- if nodetype != "Method":
- code.append(" , attr, NULL, NULL);")
- else:
- code.append(" , attr, (UA_MethodCallback) NULL, NULL, %s, inputArguments, %s, outputArguments, NULL);" % (str(len(inArgVal)), str(len(outArgVal))))
- #Adding a Node with typeDefinition = UA_NODEID_NULL will create a
- #HasTypeDefinition reference to BaseDataType - remove it since a real
- #Reference will be add in a later step (a single HasTypeDefinition reference
- #is assumed here) The current API does not let us specify IDs of Object's
- #subelements.
- if nodetype is "Object":
- code.append("UA_Server_deleteReference(server, nodeId, UA_NODEID_NUMERIC(0, 40), true, UA_EXPANDEDNODEID_NUMERIC(0, 58), true); //remove HasTypeDefinition refs generated by addObjectNode");
- if nodetype is "Variable":
- code.append("UA_Server_deleteReference(server, nodeId, UA_NODEID_NUMERIC(0, 40), true, UA_EXPANDEDNODEID_NUMERIC(0, 62), true); //remove HasTypeDefinition refs generated by addVariableNode");
- return code
- ##################
- # Node Bootstrap #
- ##################
- def getCreateNodeBootstrap(node, supressGenerationOfAttribute=[]):
- nodetype = ""
- code = []
- code.append("// Node: " + str(node) + ", " + str(node.browseName()))
- if node.nodeClass() == NODE_CLASS_OBJECT:
- nodetype = "Object"
- elif node.nodeClass() == NODE_CLASS_VARIABLE:
- nodetype = "Variable"
- elif node.nodeClass() == NODE_CLASS_METHOD:
- nodetype = "Method"
- elif node.nodeClass() == NODE_CLASS_OBJECTTYPE:
- nodetype = "ObjectType"
- elif node.nodeClass() == NODE_CLASS_REFERENCETYPE:
- nodetype = "ReferenceType"
- elif node.nodeClass() == NODE_CLASS_VARIABLETYPE:
- nodetype = "VariableType"
- elif node.nodeClass() == NODE_CLASS_DATATYPE:
- nodetype = "DataType"
- elif node.nodeClass() == NODE_CLASS_VIEW:
- nodetype = "View"
- else:
- raise Exception('Undefined NodeClass')
- code.append("UA_" + nodetype + "Node *" + node.getCodePrintableID() + \
- " = UA_NodeStore_new" + nodetype + "Node();")
- if not "browsename" in supressGenerationOfAttribute:
- extrNs = node.browseName().split(":")
- if len(extrNs) > 1:
- code.append(node.getCodePrintableID() + "->browseName = UA_QUALIFIEDNAME_ALLOC(" + \
- str(extrNs[0]) + ", \"" + extrNs[1] + "\");")
- else:
- code.append(node.getCodePrintableID() + "->browseName = UA_QUALIFIEDNAME_ALLOC(0, \"" + \
- node.browseName() + "\");")
- if not "displayname" in supressGenerationOfAttribute:
- code.append(node.getCodePrintableID() + "->displayName = UA_LOCALIZEDTEXT_ALLOC(\"en_US\", \"" + \
- node.displayName() + "\");")
- if not "description" in supressGenerationOfAttribute:
- code.append(node.getCodePrintableID() + "->description = UA_LOCALIZEDTEXT_ALLOC(\"en_US\", \"" + \
- node.description() + "\");")
- if not "writemask" in supressGenerationOfAttribute:
- if node.__node_writeMask__ != 0:
- code.append(node.getCodePrintableID() + "->writeMask = (UA_Int32) " + \
- str(node.__node_writeMask__) + ";")
- if not "userwritemask" in supressGenerationOfAttribute:
- if node.__node_userWriteMask__ != 0:
- code.append(node.getCodePrintableID() + "->userWriteMask = (UA_Int32) " + \
- str(node.__node_userWriteMask__) + ";")
- if not "nodeid" in supressGenerationOfAttribute:
- if node.id().ns != 0:
- code.append(node.getCodePrintableID() + "->nodeId.namespaceIndex = " + str(node.id().ns) + ";")
- if node.id().i != None:
- code.append(node.getCodePrintableID() + "->nodeId.identifier.numeric = " + str(node.id().i) + ";")
- elif node.id().b != None:
- code.append(node.getCodePrintableID() + "->nodeId.identifierType = UA_NODEIDTYPE_BYTESTRING;")
- logger.error("ByteString IDs for nodes has not been implemented yet.")
- return []
- elif node.id().g != None:
- #<jpfr> the string is sth like { .length = 111, .data = <ptr> }
- #<jpfr> there you _may_ alloc the <ptr> on the heap
- #<jpfr> for the guid, just set it to {.data1 = 111, .data2 = 2222, ....
- code.append(node.getCodePrintableID() + "->nodeId.identifierType = UA_NODEIDTYPE_GUID;")
- logger.error("GUIDs for nodes has not been implemented yet.")
- return []
- elif node.id().s != None:
- code.append(node.getCodePrintableID() + "->nodeId.identifierType = UA_NODEIDTYPE_STRING;")
- code.append(node.getCodePrintableID() + "->nodeId.identifier.numeric = UA_STRING_ALLOC(\"" + str(node.id().i) + "\");")
- else:
- logger.error("Node ID is not numeric, bytestring, guid or string. I do not know how to create c code for that...")
- return []
- return code
- def Node_printOpen62541CCode(node, unPrintedNodes=[], unPrintedReferences=[],
- supressGenerationOfAttribute=[]):
- """ Returns a list of strings containing the C-code necessary to intialize
- this node for the open62541 OPC-UA Stack.
- Note that this function will fail if the nodeid is non-numeric, as
- there is no UA_EXPANDEDNNODEID_[STRING|GUID|BYTESTRING] macro.
- """
- code = []
- code.append("")
- code.append("do {")
- # Just to be sure...
- if not (node in unPrintedNodes):
- logger.warn(str(node) + " attempted to reprint already printed node " + str(node)+ ".")
- return []
- # If we are being passed a parent node by the namespace, use that for registering ourselves in the namespace
- # Note: getFirstParentNode will return [parentNode, referenceToChild]
- (parentNode, parentRef) = node.getFirstParentNode()
- if not (parentNode in unPrintedNodes) and (parentNode != None) and (parentRef.referenceType() != None):
- code.append("// Referencing node found and declared as parent: " + str(parentNode .id()) + "/" +
- str(parentNode .__node_browseName__) + " using " + str(parentRef.referenceType().id()) +
- "/" + str(parentRef.referenceType().__node_browseName__))
- code.extend(getCreateNodeNoBootstrap(node, parentNode, parentRef, unPrintedNodes))
- # Parent to child reference is added by the server, do not reprint that reference
- if parentRef in unPrintedReferences:
- unPrintedReferences.remove(parentRef)
- # the UA_Server_addNode function will use addReference which creates a
- # bidirectional reference; remove any inverse references to our parent to
- # avoid duplicate refs
- for ref in node.getReferences():
- if ref.target() == parentNode and ref.referenceType() == parentRef.referenceType() and \
- ref.isForward() == False:
- while ref in unPrintedReferences:
- unPrintedReferences.remove(ref)
- # Otherwise use the "Bootstrapping" method and we will get registered with other nodes later.
- else:
- code.extend(Node_printOpen62541CCode_SubtypeEarly(node, bootstrapping = True))
- code.extend(getCreateNodeBootstrap(node, supressGenerationOfAttribute))
- code.extend(Node_printOpen62541CCode_Subtype(node, unPrintedReferences = unPrintedReferences,
- bootstrapping = True))
- code.append("// Parent node does not exist yet. This node will be bootstrapped and linked later.")
- code.append("UA_RCU_LOCK();")
- code.append("UA_NodeStore_insert(server->nodestore, (UA_Node*) " + node.getCodePrintableID() + ");")
- code.append("UA_RCU_UNLOCK();")
- # Try to print all references to nodes that already exist
- # Note: we know the reference types exist, because the namespace class made sure they were
- # the first ones being printed
- tmprefs = []
- for r in node.getReferences():
- #logger.debug("Checking if reference from " + str(r.parent()) + "can be created...")
- if not (r.target() in unPrintedNodes):
- if r in unPrintedReferences:
- if (len(tmprefs) == 0):
- code.append("// This node has the following references that can be created:")
- code.extend(getCreateStandaloneReference(node, r))
- tmprefs.append(r)
- # Remove printed refs from list
- for r in tmprefs:
- unPrintedReferences.remove(r)
- # Again, but this time check if other nodes deffered their node creation
- # because this node did not exist...
- tmprefs = []
- for r in unPrintedReferences:
- #logger.debug("Checking if another reference " + str(r.target()) + "can be created...")
- if (r.target() == node) and not (r.parent() in unPrintedNodes):
- if not isinstance(r.parent(), opcua_node_t):
- logger.debug("Reference has no parent!")
- elif not isinstance(r.parent().id(), opcua_node_id_t):
- logger.debug("Parents nodeid is not a nodeID!")
- else:
- if (len(tmprefs) == 0):
- code.append("// Creating this node has resolved the following open references:")
- code.extend(getCreateStandaloneReference(r.parent(), r))
- tmprefs.append(r)
- # Remove printed refs from list
- for r in tmprefs:
- unPrintedReferences.remove(r)
- # Again, just to be sure...
- if node in unPrintedNodes:
- # This is necessery to make printing work at all!
- unPrintedNodes.remove(node)
- code.append("} while(0);")
- return code
- def Node_printOpen62541CCode_HL_API(node, reference, supressGenerationOfAttribute=[]):
- """ Returns a list of strings containing the C-code necessary to intialize
- this node for the open62541 OPC-UA Stack using only the high level API
- Note that this function will fail if the nodeid is non-numeric, as
- there is no UA_EXPANDEDNNODEID_[STRING|GUID|BYTESTRING] macro.
- """
- code = []
- code.append("")
- code.append("do {")
- # If we are being passed a parent node by the namespace, use that for registering ourselves in the namespace
- # Note: getFirstParentNode will return [parentNode, referenceToChild]
- parentNode = reference.target()
- parentRefType = reference.referenceType()
- code.append("// Referencing node found and declared as parent: " + str(parentNode .id()) + "/" +
- str(parentNode .__node_browseName__) + " using " + str(parentRefType.id()) +
- "/" + str(parentRefType.__node_browseName__))
- code.extend(getCreateNodeNoBootstrap(node, parentNode, reference))
- code.append("} while(0);")
- return code
|