svghmi/svghmi.py
branchsvghmi
changeset 2822 9101a72a1da0
parent 2818 65f32c94d7ec
child 2823 d631f8671c75
equal deleted inserted replaced
2821:d92d201d22e1 2822:9101a72a1da0
     8 
     8 
     9 from __future__ import absolute_import
     9 from __future__ import absolute_import
    10 import os
    10 import os
    11 import shutil
    11 import shutil
    12 from itertools import izip, imap
    12 from itertools import izip, imap
    13 from pprint import pprint, pformat
    13 from pprint import pformat
    14 import hashlib
    14 import hashlib
    15 import weakref
    15 import weakref
    16 
    16 
    17 import wx
    17 import wx
    18 import wx.dataview as dv
    18 import wx.dataview as dv
    41 
    41 
    42 
    42 
    43 ScriptDirectory = paths.AbsDir(__file__)
    43 ScriptDirectory = paths.AbsDir(__file__)
    44 
    44 
    45 class HMITreeNode(object):
    45 class HMITreeNode(object):
    46     def __init__(self, path, name, nodetype, iectype = None, vartype = None, hmiclass = None):
    46     def __init__(self, path, name, nodetype, iectype = None, vartype = None, cpath = None, hmiclass = None):
    47         self.path = path
    47         self.path = path
    48         self.name = name
    48         self.name = name
    49         self.nodetype = nodetype
    49         self.nodetype = nodetype
    50         self.hmiclass = hmiclass
    50         self.hmiclass = hmiclass
    51 
    51 
    52         if iectype is not None:
    52         if iectype is not None:
    53             self.iectype = iectype
    53             self.iectype = iectype
    54             self.vartype = vartype
    54             self.vartype = vartype
       
    55             self.cpath = cpath
       
    56 
    55         if nodetype in ["HMI_NODE", "HMI_ROOT"]:
    57         if nodetype in ["HMI_NODE", "HMI_ROOT"]:
    56             self.children = []
    58             self.children = []
    57 
    59 
    58     def pprint(self, indent = 0):
    60     def pprint(self, indent = 0):
    59         res = ">"*indent + pformat(self.__dict__, indent = indent, depth = 1) + "\n"
    61         res = ">"*indent + pformat(self.__dict__, indent = indent, depth = 1) + "\n"
   131 
   133 
   132 hmi_tree_root = None
   134 hmi_tree_root = None
   133 
   135 
   134 on_hmitree_update = None
   136 on_hmitree_update = None
   135 
   137 
       
   138 SPECIAL_NODES = [("heartbeat", "HMI_INT")]
       
   139                  # ("current_page", "HMI_STRING")])
       
   140 
   136 class SVGHMILibrary(POULibrary):
   141 class SVGHMILibrary(POULibrary):
   137     def GetLibraryPath(self):
   142     def GetLibraryPath(self):
   138          return paths.AbsNeighbourFile(__file__, "pous.xml")
   143          return paths.AbsNeighbourFile(__file__, "pous.xml")
   139 
   144 
   140     def Generate_C(self, buildpath, varlist, IECCFLAGS):
   145     def Generate_C(self, buildpath, varlist, IECCFLAGS):
   141         global hmi_tree_root, on_hmitree_update, hmi_tree_unique_id
   146         global hmi_tree_root, on_hmitree_update
   142 
   147 
   143         """
   148         """
   144         PLC Instance Tree:
   149         PLC Instance Tree:
   145           prog0
   150           prog0
   146            +->v1 HMI_INT
   151            +->v1 HMI_INT
   177         # Filter known HMI types
   182         # Filter known HMI types
   178         hmi_types_instances = [v for v in varlist if v["derived"] in HMI_TYPES]
   183         hmi_types_instances = [v for v in varlist if v["derived"] in HMI_TYPES]
   179 
   184 
   180         hmi_tree_root = HMITreeNode(None, "/", "HMI_ROOT")
   185         hmi_tree_root = HMITreeNode(None, "/", "HMI_ROOT")
   181 
   186 
   182         # add special nodes
       
   183         map(lambda (n,t): hmi_tree_root.children.append(HMITreeNode(None,n,t)), [
       
   184                 ("plc_status", "HMI_PLC_STATUS"),
       
   185                 ("current_page", "HMI_CURRENT_PAGE")])
       
   186 
       
   187         # deduce HMI tree from PLC HMI_* instances
   187         # deduce HMI tree from PLC HMI_* instances
   188         for v in hmi_types_instances:
   188         for v in hmi_types_instances:
   189             path = v["C_path"].split(".")
   189             path = v["IEC_path"].split(".")
   190             # ignores variables starting with _TMP_
   190             # ignores variables starting with _TMP_
   191             if path[-1].startswith("_TMP_"):
   191             if path[-1].startswith("_TMP_"):
   192                 continue
   192                 continue
   193             derived = v["derived"]
   193             derived = v["derived"]
   194             kwargs={}
   194             kwargs={}
   195             if derived == "HMI_NODE":
   195             if derived == "HMI_NODE":
       
   196                 # TODO : make problem if HMI_NODE used in CONFIG or RESOURCE
   196                 name = path[-2]
   197                 name = path[-2]
   197                 kwargs['hmiclass'] = path[-1]
   198                 kwargs['hmiclass'] = path[-1]
   198             else:
   199             else:
   199                 name = path[-1]
   200                 name = path[-1]
   200             new_node = HMITreeNode(path, name, derived, v["type"], v["vartype"], **kwargs)
   201             new_node = HMITreeNode(path, name, derived, v["type"], v["vartype"], v["C_path"], **kwargs)
   201             hmi_tree_root.place_node(new_node)
   202             hmi_tree_root.place_node(new_node)
   202 
   203 
   203         if on_hmitree_update is not None:
   204         if on_hmitree_update is not None:
   204             on_hmitree_update()
   205             on_hmitree_update()
   205 
   206 
   206         variable_decl_array = []
   207         variable_decl_array = []
   207         extern_variables_declarations = []
   208         extern_variables_declarations = []
   208         buf_index = 0
   209         buf_index = 0
   209         item_count = 0
   210         item_count = 0
       
   211         found_heartbeat = False
       
   212 
       
   213         # find heartbeat in hmi tree
       
   214         # it is supposed to come first, but some HMI_* intances 
       
   215         # in config's globals might shift them
       
   216         hearbeat_IEC_path = ['CONFIG', 'HEARTBEAT']
   210         for node in hmi_tree_root.traverse():
   217         for node in hmi_tree_root.traverse():
   211             if hasattr(node, "iectype") and \
   218             if node.path == hearbeat_IEC_path:
   212                node.nodetype not in ["HMI_NODE"]:
   219                 hmi_tree_hearbeat_index = item_count
       
   220                 found_heartbeat = True
       
   221                 extern_variables_declarations += [
       
   222                     "#define heartbeat_index "+str(hmi_tree_hearbeat_index)
       
   223                 ]
       
   224                 break;
       
   225 
       
   226         for node in hmi_tree_root.traverse():
       
   227             if hasattr(node, "iectype") and node.nodetype != "HMI_NODE":
   213                 sz = DebugTypesSize.get(node.iectype, 0)
   228                 sz = DebugTypesSize.get(node.iectype, 0)
   214                 variable_decl_array += [
   229                 variable_decl_array += [
   215                     "{&(" + ".".join(node.path) + "), " + node.iectype + {
   230                     "{&(" + node.cpath + "), " + node.iectype + {
   216                         "EXT": "_P_ENUM",
   231                         "EXT": "_P_ENUM",
   217                         "IN":  "_P_ENUM",
   232                         "IN":  "_P_ENUM",
   218                         "MEM": "_O_ENUM",
   233                         "MEM": "_O_ENUM",
   219                         "OUT": "_O_ENUM",
   234                         "OUT": "_O_ENUM",
   220                         "VAR": "_ENUM"
   235                         "VAR": "_ENUM"
   224                 item_count += 1
   239                 item_count += 1
   225                 if len(node.path) == 1:
   240                 if len(node.path) == 1:
   226                     extern_variables_declarations += [
   241                     extern_variables_declarations += [
   227                         "extern __IEC_" + node.iectype + "_" +
   242                         "extern __IEC_" + node.iectype + "_" +
   228                         "t" if node.vartype is "VAR" else "p"
   243                         "t" if node.vartype is "VAR" else "p"
   229                         + ".".join(node.path) + ";"]
   244                         + node.cpath + ";"]
       
   245                 
       
   246         assert(found_heartbeat)
   230 
   247 
   231         # TODO : filter only requiered external declarations
   248         # TODO : filter only requiered external declarations
   232         for v in varlist :
   249         for v in varlist :
   233             if v["C_path"].find('.') < 0 and v["vartype"] == "FB" :
   250             if v["C_path"].find('.') < 0 :  # and v["vartype"] == "FB" :
   234                 extern_variables_declarations += [
   251                 extern_variables_declarations += [
   235                     "extern %(type)s %(C_path)s;" % v]
   252                     "extern %(type)s %(C_path)s;" % v]
   236 
   253 
   237         # TODO check if programs need to be declared separately
   254         # TODO check if programs need to be declared separately
   238         # "programs_declarations": "\n".join(["extern %(type)s %(C_path)s;" %
   255         # "programs_declarations": "\n".join(["extern %(type)s %(C_path)s;" %
   528             dialog.Destroy()
   545             dialog.Destroy()
   529         if open_inkscape:
   546         if open_inkscape:
   530             if not os.path.isfile(svgfile):
   547             if not os.path.isfile(svgfile):
   531                 svgfile = None
   548                 svgfile = None
   532             open_svg(svgfile)
   549             open_svg(svgfile)
       
   550 
       
   551     def CTNGlobalInstances(self):
       
   552         # view_name = self.BaseParams.getName()
       
   553         # return [ (view_name + "_" + name, iec_type, "") for name, iec_type in SPECIAL_NODES]
       
   554         # TODO : move to library level for multiple hmi
       
   555         return [(name, iec_type, "") for name, iec_type in SPECIAL_NODES]
       
   556