123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- from __future__ import print_function
- import logging
- import argparse
- from os.path import basename
- from ua_namespace import *
- from open62541_XMLPreprocessor import open62541_XMLPreprocessor
- parser = argparse.ArgumentParser(
- description="""Parse OPC UA NodeSetXML file(s) and create C code for generating nodes in open62541
- generate_open62541CCode.py will first read all XML files passed on the command
- line, then link and check the nodeset. All nodes that fulfill the basic
- requirements will then be printed as C-Code intended to be included in the
- open62541 OPC UA Server that will initialize the corresponding nodeset.""",
- formatter_class=argparse.RawDescriptionHelpFormatter)
- parser.add_argument('infiles',
- metavar="<nodeSetXML>",
- nargs='+',
- type=argparse.FileType('r'),
- help='NodeSet XML file(s). Note that the last definition of a node encountered will be used and all prior definitions are discarded.')
- parser.add_argument('outputFile',
- metavar='<outputFile>',
-
- help='The basename for the <output file>.c and <output file>.h files to be generated. This will also be the function name used in the header and c-file.')
- parser.add_argument('-i','--ignore',
- metavar="<ignoreFile>",
- type=argparse.FileType('r'),
- action='append',
- dest="ignoreFiles",
- default=[],
- help='Loads a list of NodeIDs stored in ignoreFile (one NodeID per line). The compiler will assume that these nodes have been created externally and not generate any code for them. They will however be linked to from other nodes.')
- parser.add_argument('-b','--blacklist',
- metavar="<blacklistFile>",
- type=argparse.FileType('r'),
- action='append',
- dest="blacklistFiles",
- default=[],
- help='Loads a list of NodeIDs stored in blacklistFile (one NodeID per line). Any of the nodeIds encountered in this file will be removed from the nodeset prior to compilation. Any references to these nodes will also be removed')
- parser.add_argument('-s','--suppress',
- metavar="<attribute>",
- action='append',
- dest="suppressedAttributes",
- choices=['description', 'browseName', 'displayName', 'writeMask', 'userWriteMask','nodeid'],
- default=[],
- help="Suppresses the generation of some node attributes. Currently supported options are 'description', 'browseName', 'displayName', 'writeMask', 'userWriteMask' and 'nodeid'.")
- parser.add_argument('--high-level-api',
- action='store_true', default=False,
- dest='high_level_api',
- help="Use only high level API which makes it possible to add nodes in userspace")
- parser.add_argument('-v','--verbose', action='count', help='Make the script more verbose. Can be applied up to 4 times')
- args = parser.parse_args()
- logger = logging.getLogger(__name__)
- logger.setLevel(logging.INFO)
- verbosity = 0
- if args.verbose:
- verbosity = int(args.verbose)
- if (verbosity==1):
- logging.basicConfig(level=logging.ERROR)
- elif (verbosity==2):
- logging.basicConfig(level=logging.WARNING)
- elif (verbosity==3):
- logging.basicConfig(level=logging.INFO)
- elif (verbosity>=4):
- logging.basicConfig(level=logging.DEBUG)
- else:
- logging.basicConfig(level=logging.CRITICAL)
- outfileh = open(args.outputFile+".h", r"w+")
- outfilec = open(args.outputFile+".c", r"w+")
- ns = opcua_namespace("open62541")
- preProc = open62541_XMLPreprocessor()
- for xmlfile in args.infiles:
- logger.info("Preprocessing " + str(xmlfile.name))
- preProc.addDocument(xmlfile.name)
- preProc.preprocessAll()
- for xmlfile in preProc.getPreProcessedFiles():
- logger.info("Parsing " + str(xmlfile))
- ns.parseXML(xmlfile)
- namespaceArrayNames = preProc.getUsedNamespaceArrayNames()
- for key in namespaceArrayNames:
- ns.addNamespace(key, namespaceArrayNames[key])
- for blacklist in args.blacklistFiles:
- for line in blacklist.readlines():
- line = line.replace(" ","")
- id = line.replace("\n","")
- if ns.getNodeByIDString(id) == None:
- logger.info("Can't blacklist node, namespace does currently not contain a node with id " + str(id))
- else:
- ns.removeNodeById(line)
- blacklist.close()
- logger.info("Linking namespace nodes and references")
- ns.linkOpenPointers()
- ns.sanitize()
- logger.info("Building datatype encoding rules")
- ns.buildEncodingRules()
- logger.info("Allocating variables")
- ns.allocateVariables()
- ignoreNodes = []
- for ignore in args.ignoreFiles:
- for line in ignore.readlines():
- line = line.replace(" ","")
- id = line.replace("\n","")
- if ns.getNodeByIDString(id) == None:
- logger.warn("Can't ignore node, NodeSet does currently not contain a node with id " + str(id))
- else:
- ignoreNodes.append(ns.getNodeByIDString(id))
- ignore.close()
- logger.info("Generating Header")
- generatedCode = ns.printOpen62541Header(ignoreNodes, args.suppressedAttributes, outfilename=basename(args.outputFile))
- for line in generatedCode[0]:
- print(line, end='\n', file=outfileh)
- for line in generatedCode[1]:
- print(line, end='\n', file=outfilec)
- outfilec.close()
- outfileh.close()
- logger.info("NodeSet generation code successfully printed")
|