ST code generator: when including PLCopen TC6 XML libraries (for example py_ext/pous.xml or NativeLib.xml), also includes libraries globals in result
authorEdouard Tisserant
Thu, 08 Dec 2022 11:17:15 +0100
changeset 3704 c17fac18c663
parent 3703 4b75f1506ea1
child 3705 fcf3dcc8ab3b
child 3706 39ae17a1cabe
ST code generator: when including PLCopen TC6 XML libraries (for example py_ext/pous.xml or NativeLib.xml), also includes libraries globals in result
PLCControler.py
PLCGenerator.py
POULibrary.py
--- a/PLCControler.py	Tue Nov 29 10:59:53 2022 +0100
+++ b/PLCControler.py	Thu Dec 08 11:17:15 2022 +0100
@@ -448,12 +448,12 @@
             return len(self.GetInstanceList(pou_infos, name, debug)) > 0
         return False
 
-    def GenerateProgram(self, filepath=None):
+    def GenerateProgram(self, filepath=None, **kwargs):
         errors = []
         warnings = []
         if self.Project is not None:
             try:
-                self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings)
+                self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings,**kwargs)
                 self.NextCompiledProject = self.Copy(self.Project)
                 program_text = "".join([item[0] for item in self.ProgramChunks])
                 if filepath is not None:
@@ -1147,28 +1147,35 @@
 
     def GetConfigurationExtraVariables(self):
         global_vars = []
-        for var_name, var_type, var_initial in self.GetConfNodeGlobalInstances():
-            tempvar = PLCOpenParser.CreateElement("variable", "globalVars")
-            tempvar.setname(var_name)
-
-            tempvartype = PLCOpenParser.CreateElement("type", "variable")
-            if var_type in self.GetBaseTypes():
-                tempvartype.setcontent(PLCOpenParser.CreateElement(
-                    var_type.lower()
-                    if var_type in ["STRING", "WSTRING"]
-                    else var_type, "dataType"))
+        for global_instance in self.GetConfNodeGlobalInstances():
+            if type(global_instance)==tuple:
+                # usual global without modifier from a CTN or a library
+                var_name, var_type, var_initial = global_instance
+                tempvar = PLCOpenParser.CreateElement("variable", "globalVars")
+                tempvar.setname(var_name)
+
+                tempvartype = PLCOpenParser.CreateElement("type", "variable")
+                if var_type in self.GetBaseTypes():
+                    tempvartype.setcontent(PLCOpenParser.CreateElement(
+                        var_type.lower()
+                        if var_type in ["STRING", "WSTRING"]
+                        else var_type, "dataType"))
+                else:
+                    tempderivedtype = PLCOpenParser.CreateElement("derived", "dataType")
+                    tempderivedtype.setname(var_type)
+                    tempvartype.setcontent(tempderivedtype)
+                tempvar.settype(tempvartype)
+
+                if var_initial != "":
+                    value = PLCOpenParser.CreateElement("initialValue", "variable")
+                    value.setvalue(var_initial)
+                    tempvar.setinitialValue(value)
+
+                global_vars.append(tempvar)
             else:
-                tempderivedtype = PLCOpenParser.CreateElement("derived", "dataType")
-                tempderivedtype.setname(var_type)
-                tempvartype.setcontent(tempderivedtype)
-            tempvar.settype(tempvartype)
-
-            if var_initial != "":
-                value = PLCOpenParser.CreateElement("initialValue", "variable")
-                value.setvalue(var_initial)
-                tempvar.setinitialValue(value)
-
-            global_vars.append(tempvar)
+                # case of varlists from a TC6 library
+                global_vars.append(global_instance)
+
         return global_vars
 
     # Function that returns the block definition associated to the block type given
--- a/PLCGenerator.py	Tue Nov 29 10:59:53 2022 +0100
+++ b/PLCGenerator.py	Thu Dec 08 11:17:15 2022 +0100
@@ -277,21 +277,27 @@
                   ("\n", ())]
         var_number = 0
 
-        varlists = [(varlist, varlist.getvariable()[:]) for varlist in configuration.getglobalVars()]
+        varlists = configuration.getglobalVars()[:]
 
         extra_variables = self.Controler.GetConfigurationExtraVariables()
-        extra_global_vars = None
-        if len(extra_variables) > 0 and len(varlists) == 0:
-            extra_global_vars = PLCOpenParser.CreateElement("globalVars", "interface")
-            configuration.setglobalVars([extra_global_vars])
-            varlists = [(extra_global_vars, [])]
-
-        for variable in extra_variables:
-            varlists[-1][0].appendvariable(variable)
-            varlists[-1][1].append(variable)
+        extra_CTN_globals = []
+
+        for item in extra_variables:
+            if item.getLocalTag() == "globalVars":
+                varlists.append(item)
+            else:
+                extra_CTN_globals.append(item)
+
+        if len(extra_CTN_globals) > 0:
+            extra_varlist = PLCOpenParser.CreateElement("globalVars", "interface")
+
+            for variable in extra_CTN_globals:
+                extra_varlist.appendvariable(variable)
+
+            varlists.append(extra_varlist)
 
         # Generate any global variable in configuration
-        for varlist, varlist_variables in varlists:
+        for varlist in varlists:
             variable_type = errorVarTypes.get("VAR_GLOBAL", "var_local")
             # Generate variable block with modifier
             config += [("  VAR_GLOBAL", ())]
@@ -303,7 +309,7 @@
                 config += [(" NON_RETAIN", (tagname, variable_type, (var_number, var_number + len(varlist.getvariable())), "non_retain"))]
             config += [("\n", ())]
             # Generate any variable of this block
-            for var in varlist_variables:
+            for var in varlist.getvariable():
                 vartype_content = var.gettype().getcontent()
                 if vartype_content.getLocalTag() == "derived":
                     var_type = vartype_content.getname()
@@ -331,12 +337,6 @@
                 var_number += 1
             config += [("  END_VAR\n", ())]
 
-        if extra_global_vars is not None:
-            configuration.remove(extra_global_vars)
-        else:
-            for variable in extra_variables:
-                varlists[-1][0].remove(variable)
-
         # Generate any resource in the configuration
         for resource in configuration.getresource():
             config += self.GenerateResource(resource, configuration.getname())
@@ -458,7 +458,7 @@
         return resrce
 
     # Generate the entire program for current project
-    def GenerateProgram(self, log):
+    def GenerateProgram(self, log, noconfig=False):
         log("Collecting data types")
         # Find all data types defined
         for datatype in self.Project.getdataTypes():
@@ -480,6 +480,8 @@
         for pou_name in self.PouComputed.keys():
             log("Generate POU %s"%pou_name)
             self.GeneratePouProgram(pou_name)
+        if noconfig:
+            return
         # Generate every configurations defined
         log("Generate Config(s)")
         for config in self.Project.getconfigurations():
@@ -1765,7 +1767,7 @@
         return program
 
 
-def GenerateCurrentProgram(controler, project, errors, warnings):
+def GenerateCurrentProgram(controler, project, errors, warnings, **kwargs):
     generator = ProgramGenerator(controler, project, errors, warnings)
     if hasattr(controler, "logger"):
         def log(txt):
@@ -1774,5 +1776,5 @@
         def log(txt):
             pass
 
-    generator.GenerateProgram(log)
+    generator.GenerateProgram(log,**kwargs)
     return generator.GetGeneratedProgram()
--- a/POULibrary.py	Tue Nov 29 10:59:53 2022 +0100
+++ b/POULibrary.py	Thu Dec 08 11:17:15 2022 +0100
@@ -44,7 +44,7 @@
 
     def GetSTCode(self):
         if not self.program:
-            self.program = self.LibraryControler.GenerateProgram()[0]+"\n"
+            self.program = self.LibraryControler.GenerateProgram(noconfig=True)[0]+"\n"
         return self.program
 
     def GetName(self):
@@ -65,9 +65,14 @@
 
     def GlobalInstances(self):
         """
-        @return: [(instance_name, instance_type),...]
+        @return: [varlist_object, ...]
         """
-        return []
+        varlists = []
+        for configuration in self.LibraryControler.Project.getconfigurations():
+            varlist = configuration.getglobalVars()
+            if len(varlist)>0 :
+                varlists += varlist
+        return varlists
 
     def FatalError(self, message):
         """ Raise an exception that will trigger error message intended to