svghmi/svghmi.py
branchsvghmi
changeset 2788 2ed9ff826d03
parent 2781 fbdd0fd8ee4f
child 2789 ba0dd2ec6dc4
equal deleted inserted replaced
2787:86a572fb05f8 2788:2ed9ff826d03
    75         if best_child is not None and best_child.nodetype == "HMI_LABEL":
    75         if best_child is not None and best_child.nodetype == "HMI_LABEL":
    76             best_child.place_node(node)
    76             best_child.place_node(node)
    77         else:
    77         else:
    78             self.children.append(node)
    78             self.children.append(node)
    79             
    79             
    80     def etree(self):
    80     def etree(self, add_hash=False):
    81 
    81 
    82         attribs = dict(name=self.name)
    82         attribs = dict(name=self.name)
    83         if self.path is not None:
    83         if self.path is not None:
    84             attribs["path"]=".".join(self.path)
    84             attribs["path"] = ".".join(self.path)
       
    85 
       
    86         if add_hash:
       
    87             attribs["hash"] = ",".join(map(str,self.hash()))
    85 
    88 
    86         res = etree.Element(self.nodetype, **attribs)
    89         res = etree.Element(self.nodetype, **attribs)
    87 
    90 
    88         if hasattr(self, "children"): 
    91         if hasattr(self, "children"): 
    89             for child_etree in imap(lambda c:c.etree(), self.children):
    92             for child_etree in imap(lambda c:c.etree(), self.children):
    96         if hasattr(self, "children"): 
    99         if hasattr(self, "children"): 
    97             for c in self.children:
   100             for c in self.children:
    98                 for yoodl in c.traverse():
   101                 for yoodl in c.traverse():
    99                     yield yoodl
   102                     yield yoodl
   100 
   103 
       
   104 
       
   105     def hash(self):
       
   106         """ Produce a hash, any change in HMI tree structure change that hash """
       
   107         s = hashlib.new('md5')
       
   108         self._hash(s)
       
   109         # limit size to HMI_HASH_SIZE as in svghmi.c
       
   110         return map(ord,s.digest())[:8] 
       
   111 
       
   112     def _hash(self, s):
       
   113         s.update(str((self.name,self.nodetype)))
       
   114         if hasattr(self, "children"): 
       
   115             for c in self.children:
       
   116                 c._hash(s)
       
   117 
   101 # module scope for HMITree root
   118 # module scope for HMITree root
   102 # so that CTN can use HMITree deduced in Library
   119 # so that CTN can use HMITree deduced in Library
   103 # note: this only works because library's Generate_C is 
   120 # note: this only works because library's Generate_C is 
   104 #       systematicaly invoked before CTN's CTNGenerate_C
   121 #       systematicaly invoked before CTN's CTNGenerate_C
   105 
   122 
   108 class SVGHMILibrary(POULibrary):
   125 class SVGHMILibrary(POULibrary):
   109     def GetLibraryPath(self):
   126     def GetLibraryPath(self):
   110          return paths.AbsNeighbourFile(__file__, "pous.xml")
   127          return paths.AbsNeighbourFile(__file__, "pous.xml")
   111 
   128 
   112     def Generate_C(self, buildpath, varlist, IECCFLAGS):
   129     def Generate_C(self, buildpath, varlist, IECCFLAGS):
   113         global hmi_tree_root
   130         global hmi_tree_root, hmi_tree_unique_id 
   114 
   131 
   115         """
   132         """
   116         PLC Instance Tree:
   133         PLC Instance Tree:
   117           prog0
   134           prog0
   118            +->v1 HMI_INT
   135            +->v1 HMI_INT
   168         variable_decl_array = []
   185         variable_decl_array = []
   169         extern_variables_declarations = []
   186         extern_variables_declarations = []
   170         buf_index = 0
   187         buf_index = 0
   171         item_count = 0
   188         item_count = 0
   172         for node in hmi_tree_root.traverse():
   189         for node in hmi_tree_root.traverse():
   173             if hasattr(node, "iectype"):
   190             if hasattr(node, "iectype") and \
       
   191                node.nodetype not in ["HMI_CLASS", "HMI_LABEL"]:
   174                 sz = DebugTypesSize.get(node.iectype, 0)
   192                 sz = DebugTypesSize.get(node.iectype, 0)
   175                 variable_decl_array += [
   193                 variable_decl_array += [
   176                     "{&(" + ".".join(node.path) + "), " + node.iectype + {
   194                     "{&(" + ".".join(node.path) + "), " + node.iectype + {
   177                         "EXT": "_P_ENUM",
   195                         "EXT": "_P_ENUM",
   178                         "IN":  "_P_ENUM",
   196                         "IN":  "_P_ENUM",
   208             "variable_decl_array": ",\n".join(variable_decl_array),
   226             "variable_decl_array": ",\n".join(variable_decl_array),
   209             "extern_variables_declarations": "\n".join(extern_variables_declarations),
   227             "extern_variables_declarations": "\n".join(extern_variables_declarations),
   210             "buffer_size": buf_index,
   228             "buffer_size": buf_index,
   211             "item_count": item_count,
   229             "item_count": item_count,
   212             "var_access_code": targets.GetCode("var_access.c"),
   230             "var_access_code": targets.GetCode("var_access.c"),
   213             "PLC_ticktime": self.GetCTR().GetTicktime()
   231             "PLC_ticktime": self.GetCTR().GetTicktime(),
       
   232             "hmi_hash_int": ",".join(map(str,hmi_tree_root.hash()))
   214             }
   233             }
   215 
   234 
   216         gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c")
   235         gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c")
   217         gen_svghmi_c = open(gen_svghmi_c_path, 'w')
   236         gen_svghmi_c = open(gen_svghmi_c_path, 'w')
   218         gen_svghmi_c.write(svghmi_c_code)
   237         gen_svghmi_c.write(svghmi_c_code)
   241           <xsd:attribute name="port" type="xsd:string" use="optional" default="8080"/>
   260           <xsd:attribute name="port" type="xsd:string" use="optional" default="8080"/>
   242         </xsd:complexType>
   261         </xsd:complexType>
   243       </xsd:element>
   262       </xsd:element>
   244     </xsd:schema>
   263     </xsd:schema>
   245     """
   264     """
       
   265     # TODO : add comma separated supported language list
   246 
   266 
   247     ConfNodeMethods = [
   267     ConfNodeMethods = [
   248         {
   268         {
   249             "bitmap":    "ImportSVG",
   269             "bitmap":    "ImportSVG",
   250             "name":    _("Import SVG"),
   270             "name":    _("Import SVG"),
   256             "name":    _("Inkscape"),
   276             "name":    _("Inkscape"),
   257             "tooltip": _("Edit HMI"),
   277             "tooltip": _("Edit HMI"),
   258             "method":   "_StartInkscape"
   278             "method":   "_StartInkscape"
   259         },
   279         },
   260 
   280 
       
   281         # TODO : Launch POEdit button
       
   282         #        PO -> SVG layers button
       
   283         #        SVG layers -> PO
       
   284 
   261         # TODO : HMITree button
   285         # TODO : HMITree button
   262         #        - can drag'n'drop variabes to Inkscape
   286         #        - can drag'n'drop variabes to Inkscape
   263 
   287 
   264     ]
   288     ]
   265 
   289 
   295 
   319 
   296         return res
   320         return res
   297 
   321 
   298     def GetHMITree(self):
   322     def GetHMITree(self):
   299         global hmi_tree_root
   323         global hmi_tree_root
   300         res = [hmi_tree_root.etree()]
   324         res = [hmi_tree_root.etree(add_hash=True)]
   301         return res
   325         return res
   302 
   326 
   303     def CTNGenerate_C(self, buildpath, locations):
   327     def CTNGenerate_C(self, buildpath, locations):
   304         """
   328         """
   305         Return C code generated by iec2c compiler
   329         Return C code generated by iec2c compiler