SVGHMI: draft for svghmi.c. It has all PLC variables pointed in HMI tree in an array. svghmi
authorEdouard Tisserant
Thu, 22 Aug 2019 14:58:53 +0200
branchsvghmi
changeset 2764 b75cc2cf4e50
parent 2763 ce04d79b8e57
child 2765 887aba5ef178
SVGHMI: draft for svghmi.c. It has all PLC variables pointed in HMI tree in an array.
svghmi/svghmi.c
svghmi/svghmi.py
--- a/svghmi/svghmi.c	Tue Aug 20 10:32:34 2019 +0200
+++ b/svghmi/svghmi.c	Thu Aug 22 14:58:53 2019 +0200
@@ -1,7 +1,37 @@
+#include "iec_types_all.h"
+#include "POUS.h"
+#include "config.h"
+#include "beremiz.h"
 
-void test_me(void){
-    /*
-    %(hmi_tree)s
-    */
-    return;
+%(extern_variables_declarations)s
+
+typedef const struct {
+    void *ptr;
+    __IEC_types_enum type;
+    /* TODO : w/r buffer, flags, locks */
+} hmi_tree_item_t;
+
+static hmi_tree_item_t hmi_tree_item[] = {
+%(variable_decl_array)s
+};
+
+int __init_svghmi()
+{
+    %(varinit)s
+    return 0;
 }
+
+void __cleanup_svghmi()
+{
+}
+
+void __retrieve_svghmi()
+{
+%(varret)s
+}
+
+void __publish_svghmi()
+{
+%(varpub)s
+}
+
--- a/svghmi/svghmi.py	Tue Aug 20 10:32:34 2019 +0200
+++ b/svghmi/svghmi.py	Thu Aug 22 14:58:53 2019 +0200
@@ -20,6 +20,7 @@
 from lxml import etree
 
 from util.ProcessLogger import ProcessLogger
+from runtime.typemapping import DebugTypesSize
 
 HMI_TYPES_DESC = {
     "HMI_CLASS":{},
@@ -36,10 +37,14 @@
 ScriptDirectory = paths.AbsDir(__file__)
 
 class HMITreeNode(object):
-    def __init__(self, path, name, nodetype):
+    def __init__(self, path, name, nodetype, iectype = None, vartype = None):
         self.path = path
         self.name = name
         self.nodetype = nodetype
+
+        if iectype is not None:
+            self.iectype = iectype
+            self.vartype = vartype
         if nodetype in ["HMI_LABEL", "HMI_ROOT"]:
             self.children = []
 
@@ -85,6 +90,13 @@
 
         return res
 
+    def traverse(self):
+        yield self
+        if hasattr(self, "children"): 
+            for c in self.children:
+                for yoodl in c.traverse():
+                    yield yoodl
+
 # module scope for HMITree root
 # so that CTN can use HMITree deduced in Library
 # note: this only works because library's Generate_C is 
@@ -145,21 +157,58 @@
 
         # deduce HMI tree from PLC HMI_* instances
         for v in hmi_types_instances:
-            path = v["IEC_path"].split(".")
+            path = v["C_path"].split(".")
             # ignores variables starting with _TMP_
             if path[-1].startswith("_TMP_"):
                 continue
-            new_node = HMITreeNode(path, path[-1], v["derived"])
+            new_node = HMITreeNode(path, path[-1], v["derived"], v["type"], v["vartype"])
             hmi_tree_root.place_node(new_node)
 
         print(hmi_tree_root.pprint())
 
+        variable_decl_array = []
+        extern_variables_declarations = []
+        bofs = 0
+        for node in hmi_tree_root.traverse():
+            if hasattr(node, "iectype"):
+                sz = DebugTypesSize.get(node.iectype, 0)
+                variable_decl_array += [
+                    "{&(" + ".".join(node.path) + "), " + node.iectype + {
+                        "EXT": "_P_ENUM",
+                        "IN":  "_P_ENUM",
+                        "MEM": "_O_ENUM",
+                        "OUT": "_O_ENUM",
+                        "VAR": "_ENUM"
+                    }[node.vartype] + "}"]
+                bofs += sz
+                if len(node.path) == 1:
+                    extern_variables_declarations += [
+                        "extern __IEC_" + node.iectype + "_" +
+                        "t" if node.vartype is "VAR" else "p"
+                        + ".".join(node.path) + ";"]
+
+        # TODO : filter only requiered external declarations
+        for v in varlist :
+            if v["C_path"].find('.') < 0 and v["vartype"] == "FB" :
+                extern_variables_declarations += [
+                    "extern %(type)s %(C_path)s;" % v]
+
+        # TODO check if programs need to be declared separately
+        # "programs_declarations": "\n".join(["extern %(type)s %(C_path)s;" %
+        #                                     p for p in self._ProgramList]),
+
         # TODO generate C code to observe/access HMI tree variables
         svghmi_c_filepath = paths.AbsNeighbourFile(__file__, "svghmi.c")
         svghmi_c_file = open(svghmi_c_filepath, 'r')
         svghmi_c_code = svghmi_c_file.read()
         svghmi_c_file.close()
-        svghmi_c_code = svghmi_c_code % { "hmi_tree": "TODO !!!"}
+        svghmi_c_code = svghmi_c_code % { 
+            "variable_decl_array": ",\n".join(variable_decl_array),
+            "extern_variables_declarations": "\n".join(extern_variables_declarations),
+            "varinit":"",
+            "varret":"",
+            "varpub":""
+            }
 
         gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c")
         gen_svghmi_c = open(gen_svghmi_c_path, 'w')
@@ -243,8 +292,6 @@
         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
         """
 
-        # TODO fetch HMI tree from library
-
         svgfile = self._getSVGpath()
         if os.path.exists(svgfile):
 
@@ -260,8 +307,8 @@
             # call xslt transform on Inkscape's SVG to generate XHTML
             result = transform.transform(svgdom)
            
-            print(str(result))
-            print(transform.xslt.error_log)
+            # print(str(result))
+            # print(transform.xslt.error_log)
 
             # TODO
             #   - Errors on HMI semantics