Exemplo n.º 1
0
    def generateImplementationFile(self, implementation, methodList,
                                   variableList, objectList):
        classname = toolBox_generator.getNodeCodeName(self.objectNode)

        implementation.write(
            "/* This file has been automatically generated. Remove the subsequent line to prevent any automated changes to this file\n"
        )
        implementation.write("* @generated \n")
        implementation.write("*/ \n\n")

        implementation.write("#include \"" + classname + ".hpp\"\n")
        implementation.write("extern \"C\" {\n")
        implementation.write(INDENT + "#include \"open62541.h\"\n")
        implementation.write(INDENT + "#include \"" +
                             self.generatedNamspaceFileName + ".h\"\n")
        implementation.write("}\n")
        implementation.write("#include \"ua_proxies.h\"\n")
        implementation.write("#include \"ua_proxies_callback.h\"\n")
        implementation.write("#include \"ua_proxies_typeconversion.h\"\n\n")
        implementation.write("#include <tuple>\n")

        if self.isServerClass(classname):
            self.generateServerClass(implementation, methodList, variableList,
                                     objectList)
        else:
            ## binding lib's
            self.generateClass(implementation, methodList, variableList,
                               objectList)

        self.generateDestructor(implementation, classname)
        self.generateVariable(implementation, variableList, classname)
        self.generateMethods(implementation, methodList, classname)
        self.generateClassMapSelfToNS(implementation, classname, variableList,
                                      methodList, objectList)
Exemplo n.º 2
0
    def generateServerClass(self, implementation, methodList, variableList,
                            objectList):
        classname = toolBox_generator.getNodeCodeName(self.objectNode)

        ## hard coded value "name" and "port" -> maybe bad?
        # -> needed? implementation.write("#include \"string.h\"\n\n")
        implementation.write(
            classname + "::" + classname +
            "(std::string name, uint16_t opcuaPort) : ua_mapped_class(nullptr, UA_NODEID_NULL) {\n"
        )
        implementation.write(INDENT + "this->name = name;\n")
        implementation.write(
            INDENT +
            "this->runUAServer=UA_FALSE; // Needs workerThread_setup\n")
        implementation.write(INDENT + "this->constructserver(opcuaPort);\n")
        implementation.write("}\n\n")

        ## Method "constructserver" (special ServerClass method)
        implementation.write("void " + classname +
                             "::constructserver(uint16_t opcuaPort) {\n")
        implementation.write(
            INDENT + "this->server_config = UA_ServerConfig_standard;\n")
        implementation.write(
            INDENT +
            "this->server_nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, opcuaPort);\n"
        )
        implementation.write(INDENT +
                             "this->server_config.logger = UA_Log_Stdout;\n")
        implementation.write(
            INDENT + "this->server_config.networkLayers = &this->server_nl;\n")
        implementation.write(INDENT +
                             "this->server_config.networkLayersSize = 1;\n")

        # FIXME: This should be taken from the config XML;
        implementation.write(
            INDENT +
            "this->server_config.publishingIntervalLimits = { .min = 10.0, .max = 3600.0 * 1000.0 };\n"
        )
        implementation.write(
            INDENT +
            "this->server_config.samplingIntervalLimits   = { .min = 10.0, .max = 24.0 * 3600.0 * 1000.0 };\n"
        )

        implementation.write(
            INDENT +
            "this->mappedServer = UA_Server_new(this->server_config);\n")
        # FIXME: This should be taken from the config XML; only yse UA_NS0ID_OBJECTSFOLDER as a fallback
        implementation.write(
            INDENT +
            "this->baseNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);\n"
        )
        implementation.write(
            INDENT + "//MODEL_INITIALIZER_FUNCTION(this->mappedServer);\n")
        implementation.write(INDENT + self.generatedNamspaceFileName +
                             "(this->mappedServer);\n")
        implementation.write(INDENT + "this->mapSelfToNamespace();\n")
        implementation.write("}\n\n")

        self.generateWorkerMethode(implementation, classname)
Exemplo n.º 3
0
 def generateHeaderMethods(self, header, methodList):
     # Method header
     for mn in methodList:
         header.write(
             INDENT + "UA_StatusCode " +
             toolBox_generator.getNodeCodeName(mn) +
             "(size_t inputSize, const UA_Variant *input, size_t outputSize, UA_Variant *output);\n"
         )
Exemplo n.º 4
0
 def __init__(self, namespace, objectNode, serverList=None):
     self.namespace = namespace
     self.ignoredNodes = []
     self.objectNode = objectNode
     if serverList != None and serverList.name == toolBox_generator.getNodeCodeName(
             self.objectNode):
         self.serverList = serverList
     else:
         self.serverList = None
Exemplo n.º 5
0
    def generateClass(self, implementation, methodList, variableList,
                      objectList):
        classname = toolBox_generator.getNodeCodeName(self.objectNode)

        implementation.write(
            classname + "::" + classname +
            "(std::string name, UA_NodeId baseNodeId, UA_Server* server) : ua_mapped_class(server, baseNodeId) {\n"
        )
        implementation.write(INDENT + "this->name = name;\n")
        implementation.write(INDENT + "this->mapSelfToNamespace();\n")
        implementation.write("}\n\n")
Exemplo n.º 6
0
 def generateMethods(self, implementation, methodList, classname):
     # Variable Getters/Setters
     for mn in methodList:
         # Methde Proxy
         implementation.write("UA_CALLPROXY(" + classname + ", " +
                              toolBox_generator.getNodeCodeName(mn) + ")\n")
         # Method header
         implementation.write(
             "UA_StatusCode " + classname + "::" +
             toolBox_generator.getNodeCodeName(mn) +
             "(size_t inputSize, const UA_Variant *input, size_t outputSize, UA_Variant *output) {\n"
         )
         implementation.write(INDENT +
                              "if (input == nullptr && inputSize > 0 )\n")
         implementation.write(INDENT + INDENT +
                              "return UA_STATUSCODE_BADINVALIDARGUMENT;\n")
         implementation.write(INDENT + "if (inputSize != 0)\n")
         implementation.write(INDENT + INDENT +
                              "return UA_STATUSCODE_BADINVALIDARGUMENT;\n")
         implementation.write(INDENT + "return UA_STATUSCODE_GOOD;\n")
         implementation.write("}\n\n")
Exemplo n.º 7
0
 def generateVariable(self, implementation, variableList, classname):
     # Variable Getters/Setters
     for vn in variableList:
         # Reader Proxy
         implementation.write(
             "UA_RDPROXY_" + toolBox_generator.getProxyTypeByUAType(
                 str(vn.dataType().target().browseName())) + "(" +
             classname + ", get_" + toolBox_generator.getNodeCodeName(vn) +
             ")\n")
         # Getter
         implementation.write(
             toolBox_generator.getCPPTypeByUAType(
                 str(vn.dataType().target().browseName())) + " " +
             classname + "::get_" + toolBox_generator.getNodeCodeName(vn) +
             "() {\n")
         implementation.write(INDENT + "return this->" +
                              toolBox_generator.getNodeCodeName(vn) + ";\n")
         implementation.write("}\n\n")
         # Writer Proxy
         implementation.write(
             "UA_WRPROXY_" + toolBox_generator.getProxyTypeByUAType(
                 str(vn.dataType().target().browseName())) + "(" +
             classname + ", set_" + toolBox_generator.getNodeCodeName(vn) +
             ")\n")
         # Setter
         implementation.write(
             "void " + classname + "::set_" +
             toolBox_generator.getNodeCodeName(vn) + "(" +
             toolBox_generator.getCPPTypeByUAType(
                 str(vn.dataType().target().browseName())) + " value) {\n")
         implementation.write(INDENT + "this->" +
                              toolBox_generator.getNodeCodeName(vn) +
                              " = value;\n")
         implementation.write("}\n\n")
Exemplo n.º 8
0
    def generateHeaderFile(self, header, methodList, variableList, objectList):
        classname = toolBox_generator.getNodeCodeName(self.objectNode)

        header.write(
            "/* This file has been automatically generated. Remove the subsequent line to prevent any automated changes to this file\n"
        )
        header.write("* @generated \n")
        header.write("*/ \n\n")

        # Print Header Guards
        header.write("#ifndef HAVE_" + classname.capitalize() + "_H\n")
        header.write("#define HAVE_" + classname.capitalize() + "_H\n\n")

        if self.isServerClass(classname):
            header.write("#include <ipc_managed_object.h>\n")
        header.write("#include \"ua_mapped_class.h\"\n\n")

        if self.isServerClass(classname):
            header.write("class " + classname +
                         " : public ipc_managed_object, ua_mapped_class {\n")
            header.write("private:\n")
            header.write(INDENT + "UA_Boolean runUAServer;\n")
            header.write(INDENT + "std::thread *serverThread;\n")
        else:
            header.write("class " + classname + " : ua_mapped_class {\n")
            header.write("private:\n")
        header.write(INDENT + "std::string name;\n")
        header.write(INDENT + "UA_NodeId rootNodeId;\n")

        if self.isServerClass(classname):
            self.generateHeaderServerVariables(header, variableList)
            for vn in variableList:
                header.write(INDENT + toolBox_generator.getCPPTypeByUAType(
                    str(vn.dataType().target().browseName())) + " " +
                             toolBox_generator.getNodeCodeName(vn) + ";\n")
            self.generateHeaderServerMethoden(header)
            print("generate server header file")
        else:
            for vn in variableList:
                header.write(INDENT + toolBox_generator.getCPPTypeByUAType(
                    str(vn.dataType().target().browseName())) + " " +
                             toolBox_generator.getNodeCodeName(vn) + ";\n")
            print("generate standard header file")
        '''
    ' Do we need this kind of object?! You should think about...
    '
    '''
        '''#objectList
    ' for on in objectList:
    '  header.write(INDENT + "//FIXME " + toolBox_generator.getCPPTypeByUAType(str(on.id())) + " " + toolBox_generator.getNodeCodeName(on) + ";\n")
    '''

        header.write("\n")
        for on in objectList:
            header.write(INDENT + "UA_NodeId " +
                         toolBox_generator.getNodeCodeName(on) + ";\n")
        header.write("\n")
        header.write(INDENT + "UA_StatusCode mapSelfToNamespace();\n")
        header.write("\n")
        header.write("protected:\n")
        header.write("\n")
        header.write("public:\n")

        if self.isServerClass(classname):
            header.write(INDENT + classname +
                         "(std::string name, uint16_t opcuaPort);\n")
            header.write(INDENT + "void workerThread_setup();\n")
            header.write(INDENT + "void workerThread_iterate();\n")
            header.write(INDENT + "void workerThread_cleanup();\n")
        else:
            header.write(
                INDENT + classname +
                "(std::string name, UA_NodeId baseNodeId, UA_Server* server);\n"
            )
        header.write(INDENT + "~" + classname + "();\n")
        header.write("\n")
        header.write(INDENT + "// Getter and Setter functions \n")
        for vn in variableList:
            header.write(INDENT + toolBox_generator.getCPPTypeByUAType(
                str(vn.dataType().target().browseName())) + " get_" +
                         toolBox_generator.getNodeCodeName(vn) + "();\n")
            header.write(INDENT + "void set_" +
                         toolBox_generator.getNodeCodeName(vn) + "(" +
                         toolBox_generator.getCPPTypeByUAType(
                             str(vn.dataType().target().browseName())) +
                         " value);\n")
            header.write("\n")

        self.generateHeaderMethods(header, methodList)

        header.write("\n")
        header.write("};\n")
        header.write("\n#endif // Header guard\n")
Exemplo n.º 9
0
    def generateClassMapSelfToNS(self, implementation, classname, variableList,
                                 methodList, objectList):
        ## Lastly, always add mapSelfToNamespace
        implementation.write("UA_StatusCode " + classname +
                             "::mapSelfToNamespace() {\n")

        # Create base node
        implementation.write(INDENT + "/* Create Root Node */")
        implementation.write(INDENT +
                             "UA_StatusCode retval = UA_STATUSCODE_GOOD;\n")
        implementation.write(INDENT +
                             "UA_NodeId createdNodeId = UA_NODEID_NULL;\n")
        implementation.write("\n")
        implementation.write(
            INDENT +
            "if (UA_NodeId_equal(&this->baseNodeId, &createdNodeId) == UA_TRUE) { \n"
        )
        implementation.write(
            INDENT + INDENT +
            "return 0; // Something went UA_WRING (initializer should have set this!)\n"
        )
        implementation.write(INDENT + "}\n\n")
        implementation.write("\n")
        implementation.write(INDENT + "UA_ObjectAttributes oAttr;\n")
        implementation.write(
            INDENT +
            "oAttr.displayName = UA_LOCALIZEDTEXT_ALLOC((char*)\"en_US\", this->name.c_str());\n"
        )
        implementation.write(
            INDENT +
            "oAttr.description = UA_LOCALIZEDTEXT_ALLOC((char*)\"en_US\", this->name.c_str());\n"
        )
        implementation.write("\n")

        implementation.write(INDENT + "UA_INSTATIATIONCALLBACK(icb);\n")
        implementation.write(
            INDENT +
            "UA_Server_addObjectNode(this->mappedServer, UA_NODEID_NUMERIC(1,0),\n"
        )
        if self.serverList != None and self.serverList.baseNodeId != None:
            # BaseNodeId from config
            implementation.write(
                INDENT + INDENT + INDENT +
                toolBox_generator.getNodeIdInitializerFromNodeId(
                    self.serverList.baseNodeIdAsUAType()) +
                ", UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),\n")
        else:
            implementation.write(
                INDENT + INDENT + INDENT +
                "UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),\n"
            )
        implementation.write(
            INDENT + INDENT + INDENT +
            "UA_QUALIFIEDNAME_ALLOC(1, this->name.c_str()), " +
            toolBox_generator.getNodeIdInitializer(self.objectNode) +
            ", oAttr, &icb, &createdNodeId);\n")
        implementation.write(
            INDENT + "UA_NodeId_copy(&createdNodeId, &this->rootNodeId);\n\n")

        # Map function calls
        implementation.write(INDENT + "\n/* Contained Functions */\n")
        implementation.write(INDENT + "UA_FunctionCall_Map mapThis;\n")
        for mn in methodList:
            implementation.write(
                INDENT +
                "mapThis.push_back((UA_FunctionCall_Map_Element) {.typeTemplateId = "
                + toolBox_generator.getNodeIdInitializer(mn) +
                ", .lookupTable = UA_CALLPROXY_TABLE(" + classname + ", " +
                toolBox_generator.getNodeCodeName(mn) +
                "), .callback = UA_CALLPROXY_NAME(" + classname + ", " +
                toolBox_generator.getNodeCodeName(mn) + ") }); \n")

        implementation.write(INDENT +
                             "\n/* Contained variables & Proxy mapping */\n")
        implementation.write(
            INDENT +
            "this->ua_mapFunctions(this, &mapThis, createdNodeId);\n\n")
        # Map DataSources
        implementation.write(INDENT + "UA_DataSource_Map mapDs;\n")
        # create for every var setter/getter proxys

        for vn in variableList:
            implementation.write(
                INDENT +
                "mapDs.push_back((UA_DataSource_Map_Element) { .typeTemplateId ="
                + toolBox_generator.getNodeIdInitializer(vn) +
                ", .read=UA_RDPROXY_NAME(" + classname + ", get_" +
                toolBox_generator.getNodeCodeName(vn) +
                "), .write=UA_WRPROXY_NAME(" + classname + ", set_" +
                toolBox_generator.getNodeCodeName(vn) + ")});\n")

        implementation.write(
            INDENT +
            "ua_callProxy_mapDataSources(this->mappedServer, this->ownedNodes, &mapDs, (void *) this);\n"
        )

        implementation.write(INDENT + "\n/* Contained Objects */\n")
        implementation.write(INDENT + "UA_NodeId *tmpNodeId;\n")
        for on in objectList:
            implementation.write(
                INDENT +
                "tmpNodeId = nodePairList_getTargetIdBySourceId(this->ownedNodes, "
                + toolBox_generator.getNodeIdInitializer(on) + ");\n")
            implementation.write(INDENT + "if(tmpNodeId != nullptr)\n")
            implementation.write(INDENT + INDENT +
                                 "UA_NodeId_copy( tmpNodeId, &this->" +
                                 toolBox_generator.getNodeCodeName(on) +
                                 ");\n")

        implementation.write(INDENT + "return UA_STATUSCODE_GOOD;\n")
        implementation.write("}\n\n")
Exemplo n.º 10
0
    def getMembersOfType(self, objectNode):
        variables = []
        objects = []
        methods = []

        # Return a Triple of (varibales, objects, methods) for a given type definition
        for r in objectNode.getReferences():
            if r.isForward() and r.target() != None:
                # FIXME: We are only checking hasProperty & hasComponent, but we should be checking any derived refType as well...
                if((r.target().nodeClass() == NODE_CLASS_VARIABLE or r.target().nodeClass() == NODE_CLASS_VARIABLETYPE)) and \
                (r.referenceType().id().ns == 0 and r.referenceType().id().i == 46 or
                 r.referenceType().id().ns == 0 and r.referenceType().id().i == 47 ):
                    vn = r.target()
                    if (vn.dataType() != None):
                        print("+-Variable" +
                              toolBox_generator.getNodeCodeName(r.target()))
                        # Only create encodable types!
                        if not "NonMappableType" in toolBox_generator.getCPPTypeByUAType(
                                str(vn.dataType().target().browseName())):
                            vnames = []
                            for v in variables:
                                vnames.append(
                                    toolBox_generator.getNodeCodeName(v))
                            if not toolBox_generator.getNodeCodeName(
                                    r.target()) in vnames:
                                variables.append(vn)
                        if not r.target() in self.ignoredNodes:
                            t = self.getMembersOfType(r.target())
                            variables += t[0]
                            objects += t[1]
                            methods += t[2]
                # FIXME: We are only checking hasProperty & hasComponent, but we should be checking any derived refType as well...
                if (r.target().nodeClass() == NODE_CLASS_OBJECT)  and \
                (r.referenceType().id().ns == 0 and r.referenceType().id().i == 46 or
                 r.referenceType().id().ns == 0 and r.referenceType().id().i == 47 ):
                    print("+-Object" +
                          toolBox_generator.getNodeCodeName(r.target()))
                    if not r.target() in self.ignoredNodes:
                        print("-- contains -->" +
                              toolBox_generator.getNodeCodeName(r.target()))
                        t = self.getMembersOfType(r.target())
                        variables += t[0]
                        objects += t[1]
                        methods += t[2]
                    onames = []
                    for o in objects:
                        onames.append(toolBox_generator.getNodeCodeName(o))
                    if not toolBox_generator.getNodeCodeName(
                            r.target()) in onames:
                        objects.append(r.target())
                if(r.target().nodeClass() == NODE_CLASS_METHOD)  and \
                (r.referenceType().id().ns == 0 and r.referenceType().id().i == 46 or
                 r.referenceType().id().ns == 0 and r.referenceType().id().i == 47 ):
                    print("+-Method" +
                          toolBox_generator.getNodeCodeName(r.target()))
                    methods.append(r.target())
            ## If this type inherits attributes from its parent, we need to add these to this objects list of variables/objects/methods
            # FIXME: We are only checking hasSubtype, but we should be checking any derived refType as well...
            if not r.isForward() and r.target() != None and r.referenceType(
            ).id().ns == 0 and r.referenceType().id().i == 45:
                if not r.target() in self.ignoredNodes:
                    print("-- supertype -->" +
                          toolBox_generator.getNodeCodeName(r.target()))
                    t = self.getMembersOfType(r.target())
                    variables += t[0]
                    objects += t[1]
                    methods += t[2]
        return (variables, objects, methods)
Exemplo n.º 11
0
    def generateAll(self, outputPath):
        for objectNode in self.namespace.nodes:
            # TODO: clientReflection classes
            if objectNode.nodeClass(
            ) == NODE_CLASS_OBJECTTYPE and not objectNode in self.ignoredNodes:
                classname = toolBox_generator.getNodeCodeName(objectNode)
                print(classname + ".cpp, " + classname + ".hpp")
                cppPath = outputPath + "/serverReflection/"
                hppPath = cppPath
                if not os.path.exists(cppPath):
                    os.makedirs(cppPath)
                if not os.path.exists(hppPath):
                    os.makedirs(hppPath)

                logger.debug("Generating ObjectType " + str(objectNode.id()) +
                             " " + classname)
                methods = []
                variables = []
                objects = []
                print("Discovering generatable subnodes")
                (variables, objects,
                 methods) = self.getMembersOfType(objectNode)

                ## create all files
                classname = toolBox_generator.getNodeCodeName(objectNode)
                config = None
                for serverConfig in self.serverHostList:
                    if serverConfig.name == classname:
                        config = serverConfig
                cppfile = cppfile_generator(self.generatedNamspaceFileName,
                                            objectNode, config)
                hppfile = headerfile_generator(self.namespace, objectNode,
                                               config)
                '''
        ' Check if file still exist.
        ' If there is a "@generated" string in the first lines of code, the file can be reprinted
        ' if not, the file was changed by an human or somethink like a human... hence we dont touch it with the generator
        '''
                if os.path.isfile(cppPath + classname + ".cpp"):
                    existingCodeFile = open(cppPath + classname + ".cpp")
                    for line in existingCodeFile:
                        if (string.find(line.rstrip(), "@generated") != -1):
                            codefile = open(cppPath + classname + ".cpp",
                                            r"w+")
                            cppfile.generateImplementationFile(
                                codefile, methods, variables, objects)
                            codefile.close()
                            break
                        else:
                            logger.warn(
                                cppPath + classname +
                                ".cpp has been modified (is missing the @generated comment). Skipping code generation for this class"
                            )
                    existingCodeFile.close()

                else:
                    codefile = open(cppPath + classname + ".cpp", r"w+")
                    cppfile.generateImplementationFile(codefile, methods,
                                                       variables, objects)
                    codefile.close()

                if os.path.isfile(hppPath + classname + ".hpp"):
                    existingCodeFile = open(hppPath + classname + ".hpp")
                    for line in existingCodeFile:
                        if (string.find(line.rstrip(), "@generated") != -1):
                            headerfile = open(hppPath + classname + ".hpp",
                                              r"w+")
                            hppfile.generateHeaderFile(headerfile, methods,
                                                       variables, objects)
                            headerfile.close()
                            break
                        else:
                            logger.warn(
                                cppPath + classname +
                                ".hpp has been modified (is missing the @generated comment). Skipping code generation for this class"
                            )
                    existingCodeFile.close()
                else:
                    headerfile = open(hppPath + classname + ".hpp", r"w+")
                    hppfile.generateHeaderFile(headerfile, methods, variables,
                                               objects)
                    headerfile.close()