generate_open62541CCode.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #!/usr/bin/env/python
  2. # -*- coding: utf-8 -*-
  3. ###
  4. ### Author: Chris Iatrou (ichrispa@core-vector.net)
  5. ### Version: rev 13
  6. ###
  7. ### This program was created for educational purposes and has been
  8. ### contributed to the open62541 project by the author. All licensing
  9. ### terms for this source is inherited by the terms and conditions
  10. ### specified for by the open62541 project (see the projects readme
  11. ### file for more information on the LGPL terms and restrictions).
  12. ###
  13. ### This program is not meant to be used in a production environment. The
  14. ### author is not liable for any complications arising due to the use of
  15. ### this program.
  16. ###
  17. from sys import argv, exit
  18. from os import path
  19. from ua_namespace import *
  20. from logger import *
  21. def usage():
  22. print "Skript usage:"
  23. print "generate_open62541CCode <namespace XML> [namespace.xml[ namespace.xml[...]]] <output file>"
  24. print ""
  25. print "generate_open62541CCode will first read all XML files passed on the command line, then "
  26. print "link and check the namespace. All nodes that fullfill the basic requirements will then be"
  27. print "printed as C-Code intended to be included in the open62541 OPC-UA Server that will"
  28. print "initialize the corresponding name space."
  29. if __name__ == '__main__':
  30. # Check if the parameters given correspond to actual files
  31. infiles = []
  32. ouffile = ""
  33. GLOBAL_LOG_LEVEL = LOG_LEVEL_INFO
  34. if len(argv) < 2:
  35. usage()
  36. exit(1)
  37. for filename in argv[1:-1]:
  38. if path.exists(filename):
  39. infiles.append(filename)
  40. else:
  41. log(None, "File " + str(filename) + " does not exist.", LOG_LEVEL_ERROR)
  42. usage()
  43. exit(1)
  44. # Creating the header is tendious. We can skip the entire process if
  45. # the header exists.
  46. if path.exists(argv[-1]):
  47. log(None, "File " + str(filename) + " does already exists.", LOG_LEVEL_INFO)
  48. log(None, "Header generation will be skipped. Delete the header and rerun this script if necessary.", LOG_LEVEL_INFO)
  49. exit(0)
  50. # Open the output file
  51. outfile = open(argv[-1], r"w+")
  52. # Create a new namespace
  53. # Note that the name is actually completely symbolic, it has no other
  54. # function but to distinguish this specific class.
  55. # A namespace class acts as a container for nodes. The nodes may belong
  56. # to any number of different OPC-UA namespaces.
  57. ns = opcua_namespace("open62541")
  58. # Parse the XML files
  59. for xmlfile in infiles:
  60. log(None, "Parsing " + str(xmlfile), LOG_LEVEL_INFO)
  61. ns.parseXML(xmlfile)
  62. # Link the references in the namespace
  63. log(None, "Linking namespace nodes and references", LOG_LEVEL_INFO)
  64. ns.linkOpenPointers()
  65. # Remove nodes that are not printable or contain parsing errors, such as
  66. # unresolvable or no references or invalid NodeIDs
  67. ns.sanitize()
  68. # Parse Datatypes in order to find out what the XML keyed values actually
  69. # represent.
  70. # Ex. <rpm>123</rpm> is not encodable
  71. # only after parsing the datatypes, it is known that
  72. # rpm is encoded as a double
  73. log(None, "Building datatype encoding rules", LOG_LEVEL_INFO)
  74. ns.buildEncodingRules()
  75. # Allocate/Parse the data values. In order to do this, we must have run
  76. # buidEncodingRules.
  77. log(None, "Allocating variables", LOG_LEVEL_INFO)
  78. ns.allocateVariables()
  79. # Create the C Code
  80. log(None, "Generating Header", LOG_LEVEL_INFO)
  81. for line in ns.printOpen62541Header():
  82. outfile.write(line+"\n")
  83. outfile.close()