svghmi/svghmi.py
branchsvghmi
changeset 2764 b75cc2cf4e50
parent 2763 ce04d79b8e57
child 2765 887aba5ef178
equal deleted inserted replaced
2763:ce04d79b8e57 2764:b75cc2cf4e50
    18 from POULibrary import POULibrary
    18 from POULibrary import POULibrary
    19 from docutil import open_svg, get_inkscape_path
    19 from docutil import open_svg, get_inkscape_path
    20 from lxml import etree
    20 from lxml import etree
    21 
    21 
    22 from util.ProcessLogger import ProcessLogger
    22 from util.ProcessLogger import ProcessLogger
       
    23 from runtime.typemapping import DebugTypesSize
    23 
    24 
    24 HMI_TYPES_DESC = {
    25 HMI_TYPES_DESC = {
    25     "HMI_CLASS":{},
    26     "HMI_CLASS":{},
    26     "HMI_LABEL":{},
    27     "HMI_LABEL":{},
    27     "HMI_STRING":{},
    28     "HMI_STRING":{},
    34 from XSLTransform import XSLTransform
    35 from XSLTransform import XSLTransform
    35 
    36 
    36 ScriptDirectory = paths.AbsDir(__file__)
    37 ScriptDirectory = paths.AbsDir(__file__)
    37 
    38 
    38 class HMITreeNode(object):
    39 class HMITreeNode(object):
    39     def __init__(self, path, name, nodetype):
    40     def __init__(self, path, name, nodetype, iectype = None, vartype = None):
    40         self.path = path
    41         self.path = path
    41         self.name = name
    42         self.name = name
    42         self.nodetype = nodetype
    43         self.nodetype = nodetype
       
    44 
       
    45         if iectype is not None:
       
    46             self.iectype = iectype
       
    47             self.vartype = vartype
    43         if nodetype in ["HMI_LABEL", "HMI_ROOT"]:
    48         if nodetype in ["HMI_LABEL", "HMI_ROOT"]:
    44             self.children = []
    49             self.children = []
    45 
    50 
    46     def pprint(self, indent = 0):
    51     def pprint(self, indent = 0):
    47         res = ">"*indent + pformat(self.__dict__, indent = indent, depth = 1) + "\n"
    52         res = ">"*indent + pformat(self.__dict__, indent = indent, depth = 1) + "\n"
    83             for child_etree in imap(lambda c:c.etree(), self.children):
    88             for child_etree in imap(lambda c:c.etree(), self.children):
    84                 res.append(child_etree)
    89                 res.append(child_etree)
    85 
    90 
    86         return res
    91         return res
    87 
    92 
       
    93     def traverse(self):
       
    94         yield self
       
    95         if hasattr(self, "children"): 
       
    96             for c in self.children:
       
    97                 for yoodl in c.traverse():
       
    98                     yield yoodl
       
    99 
    88 # module scope for HMITree root
   100 # module scope for HMITree root
    89 # so that CTN can use HMITree deduced in Library
   101 # so that CTN can use HMITree deduced in Library
    90 # note: this only works because library's Generate_C is 
   102 # note: this only works because library's Generate_C is 
    91 #       systematicaly invoked before CTN's CTNGenerate_C
   103 #       systematicaly invoked before CTN's CTNGenerate_C
    92 
   104 
   143                 ("plc_status", "HMI_PLC_STATUS"),
   155                 ("plc_status", "HMI_PLC_STATUS"),
   144                 ("current_page", "HMI_CURRENT_PAGE")])
   156                 ("current_page", "HMI_CURRENT_PAGE")])
   145 
   157 
   146         # deduce HMI tree from PLC HMI_* instances
   158         # deduce HMI tree from PLC HMI_* instances
   147         for v in hmi_types_instances:
   159         for v in hmi_types_instances:
   148             path = v["IEC_path"].split(".")
   160             path = v["C_path"].split(".")
   149             # ignores variables starting with _TMP_
   161             # ignores variables starting with _TMP_
   150             if path[-1].startswith("_TMP_"):
   162             if path[-1].startswith("_TMP_"):
   151                 continue
   163                 continue
   152             new_node = HMITreeNode(path, path[-1], v["derived"])
   164             new_node = HMITreeNode(path, path[-1], v["derived"], v["type"], v["vartype"])
   153             hmi_tree_root.place_node(new_node)
   165             hmi_tree_root.place_node(new_node)
   154 
   166 
   155         print(hmi_tree_root.pprint())
   167         print(hmi_tree_root.pprint())
       
   168 
       
   169         variable_decl_array = []
       
   170         extern_variables_declarations = []
       
   171         bofs = 0
       
   172         for node in hmi_tree_root.traverse():
       
   173             if hasattr(node, "iectype"):
       
   174                 sz = DebugTypesSize.get(node.iectype, 0)
       
   175                 variable_decl_array += [
       
   176                     "{&(" + ".".join(node.path) + "), " + node.iectype + {
       
   177                         "EXT": "_P_ENUM",
       
   178                         "IN":  "_P_ENUM",
       
   179                         "MEM": "_O_ENUM",
       
   180                         "OUT": "_O_ENUM",
       
   181                         "VAR": "_ENUM"
       
   182                     }[node.vartype] + "}"]
       
   183                 bofs += sz
       
   184                 if len(node.path) == 1:
       
   185                     extern_variables_declarations += [
       
   186                         "extern __IEC_" + node.iectype + "_" +
       
   187                         "t" if node.vartype is "VAR" else "p"
       
   188                         + ".".join(node.path) + ";"]
       
   189 
       
   190         # TODO : filter only requiered external declarations
       
   191         for v in varlist :
       
   192             if v["C_path"].find('.') < 0 and v["vartype"] == "FB" :
       
   193                 extern_variables_declarations += [
       
   194                     "extern %(type)s %(C_path)s;" % v]
       
   195 
       
   196         # TODO check if programs need to be declared separately
       
   197         # "programs_declarations": "\n".join(["extern %(type)s %(C_path)s;" %
       
   198         #                                     p for p in self._ProgramList]),
   156 
   199 
   157         # TODO generate C code to observe/access HMI tree variables
   200         # TODO generate C code to observe/access HMI tree variables
   158         svghmi_c_filepath = paths.AbsNeighbourFile(__file__, "svghmi.c")
   201         svghmi_c_filepath = paths.AbsNeighbourFile(__file__, "svghmi.c")
   159         svghmi_c_file = open(svghmi_c_filepath, 'r')
   202         svghmi_c_file = open(svghmi_c_filepath, 'r')
   160         svghmi_c_code = svghmi_c_file.read()
   203         svghmi_c_code = svghmi_c_file.read()
   161         svghmi_c_file.close()
   204         svghmi_c_file.close()
   162         svghmi_c_code = svghmi_c_code % { "hmi_tree": "TODO !!!"}
   205         svghmi_c_code = svghmi_c_code % { 
       
   206             "variable_decl_array": ",\n".join(variable_decl_array),
       
   207             "extern_variables_declarations": "\n".join(extern_variables_declarations),
       
   208             "varinit":"",
       
   209             "varret":"",
       
   210             "varpub":""
       
   211             }
   163 
   212 
   164         gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c")
   213         gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c")
   165         gen_svghmi_c = open(gen_svghmi_c_path, 'w')
   214         gen_svghmi_c = open(gen_svghmi_c_path, 'w')
   166         gen_svghmi_c.write(svghmi_c_code)
   215         gen_svghmi_c.write(svghmi_c_code)
   167         gen_svghmi_c.close()
   216         gen_svghmi_c.close()
   241         when _generate_softPLC have been called
   290         when _generate_softPLC have been called
   242         @param locations: ignored
   291         @param locations: ignored
   243         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   292         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   244         """
   293         """
   245 
   294 
   246         # TODO fetch HMI tree from library
       
   247 
       
   248         svgfile = self._getSVGpath()
   295         svgfile = self._getSVGpath()
   249         if os.path.exists(svgfile):
   296         if os.path.exists(svgfile):
   250 
   297 
   251             # TODO : move to __init__
   298             # TODO : move to __init__
   252             transform = XSLTransform(os.path.join(ScriptDirectory, "gen_index_xhtml.xslt"),
   299             transform = XSLTransform(os.path.join(ScriptDirectory, "gen_index_xhtml.xslt"),
   258             svgdom = etree.parse(svgfile)
   305             svgdom = etree.parse(svgfile)
   259 
   306 
   260             # call xslt transform on Inkscape's SVG to generate XHTML
   307             # call xslt transform on Inkscape's SVG to generate XHTML
   261             result = transform.transform(svgdom)
   308             result = transform.transform(svgdom)
   262            
   309            
   263             print(str(result))
   310             # print(str(result))
   264             print(transform.xslt.error_log)
   311             # print(transform.xslt.error_log)
   265 
   312 
   266             # TODO
   313             # TODO
   267             #   - Errors on HMI semantics
   314             #   - Errors on HMI semantics
   268             #   - ... maybe something to have a global view of what is declared in SVG.
   315             #   - ... maybe something to have a global view of what is declared in SVG.
   269 
   316