plugin framework organization being defined
authoretisserant
Tue, 21 Aug 2007 17:21:26 +0200
changeset 12 a1f9e514f708
parent 11 75ae893d5eed
child 13 f1f0edbeb313
plugin framework organization being defined
.cvsignore
Beremiz.py
plugins/README.plugins
plugins/__init__.py
plugins/__templates.py
plugins/canfestival/__init__.py
plugins/canfestival/canfestival.py
plugins/svgui/svgui.py
--- a/.cvsignore	Mon Aug 20 14:28:08 2007 +0200
+++ b/.cvsignore	Tue Aug 21 17:21:26 2007 +0200
@@ -1,1 +1,4 @@
 *.pyc
+.settings
+.pydevproject
+.project
--- a/Beremiz.py	Mon Aug 20 14:28:08 2007 +0200
+++ b/Beremiz.py	Tue Aug 21 17:21:26 2007 +0200
@@ -31,13 +31,14 @@
 base_folder = os.path.split(sys.path[0])[0]
 sys.path.append(os.path.join(base_folder, "plcopeneditor"))
 sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
+sys.path.append(os.path.join(base_folder, "wxsvg", "svgui", "defeditor"))
 
 iec2cc_path = os.path.join(base_folder, "matiec", "iec2cc")
 ieclib_path = os.path.join(base_folder, "matiec", "lib")
 
 from PLCOpenEditor import PLCOpenEditor, ProjectDialog
 from TextViewer import TextViewer
-from plcopen.structures import IEC_KEYWORDS, AddPlugin
+from plcopen.structures import IEC_KEYWORDS#, AddPlugin
 from PLCControler import PLCControler
 
 import plugins
@@ -333,12 +334,8 @@
         
         for name in plugins.__all__:
             module = getattr(plugins, name)
-            if len(module.BlockList) > 0:
-                function = module.GetBlockGenerationFunction(self)
-                blocklist = module.BlockList
-                for blocktype in blocklist["list"]:
-                    blocktype["generate"] = function
-                AddPlugin(module.BlockList)
+            
+			#AddPlugin(module.GetBlockGenerationFunction(self))
         
         self.CurrentProjectPath = ""
         
@@ -664,15 +661,15 @@
             ready = select.select([outfd,errfd],[],[]) # wait for input
             if outfd in ready[0]:
                 outchunk = outfile.readline()
-                if outchunk == '': outeof = 1
+                if outchunk == '': outeof = 1 
+                else : outlen += 1
                 outdata += outchunk
-                outlen += 1
                 self.Log.write(outchunk)
             if errfd in ready[0]:
                 errchunk = errfile.readline()
-                if errchunk == '': erreof = 1
+                if errchunk == '': erreof = 1 
+                else : errlen += 1
                 errdata += errchunk
-                errlen += 1
                 self.Log.write_warning(errchunk)
             if outeof and erreof : break
             if errlen > sz_limit or outlen > sz_limit : 
@@ -705,6 +702,9 @@
                     ST_viewer.SetText(file(plc_file).read())
                     new_dialog.Show()
                     raise Exception, "Error : IEC to C compiler returned %d"%status
+                C_files = result.splitlines()
+                C_files.remove("POUS.c")
+                C_files = map(lambda filename:os.path.join(self.TargetDir, filename), C_files)
                 self.Log.write("Extracting Located Variables...\n")
                 location_file = open(os.path.join(self.TargetDir,"LOCATED_VARIABLES.h"))
                 locations = []
@@ -715,12 +715,15 @@
                         locations.append(result.groups())
                 self.Log.write("Generating Network Configurations...\n")
                 for bus_id, bus_infos in self.BusManagers.items():
-                    if bus_infos["Manager"]:
-                        filepath = "%s.c"%os.path.join(self.TargetDir, gen_cfile.FormatName(bus_infos["Name"]))
-                        result = bus_infos["Manager"].GenerateBus(filepath, bus_id, locations)
+                   if bus_infos["Manager"]:
+                        c_filename = "%s.c"%os.path.join(self.TargetDir, gen_cfile.FormatName(bus_infos["Name"]))
+                        result = bus_infos["Manager"].GenerateBus(c_filename, locations)
                         if result:
-                            raise Exception, "Bus with id \"0x%2.2X\" can't be generated!"%bus_id
+                            raise Exception
+                        else:
+                            C_files.append(c_filename)
                 self.Log.write("Generating Makefiles...\n")
+                self.Log.write(str(C_files))
                 
                 self.Log.write("Compiling Project...\n")
                 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/README.plugins	Tue Aug 21 17:21:26 2007 +0200
@@ -0,0 +1,28 @@
+	BlockTypesFactory(beremiz_inst)
+		return list similar to plcopeneditor/plcopen/structure.py BlockTypes
+	[ST_LibraryFactory(beremiz_inst)]
+		
+	[C_Library -- "C Code"]
+	Build -- {"CC":"gcc" , "C_FLAGS" : "..." , "LD_FLAGS" : "..." , ... ,}
+	Plugin_Params_XSD -- Defini les paramertres optionels du plugin
+	Plugin_Controller_Factory -- Sert a instancier chaque controler de bus
+		+ GenerateC(bus_controler_list) -> C_file
+			[canfestival : InitNodes(){0_post_init(); 1_post_init();}]
+			plugname_pre_init(){...}
+			plugname_post_init(){[canfestival : StarTimerLoop(&InitNodes)]}
+		+ Save/Load XML
+	Bus_Params_XSD -- Defini les paramertres optionels du bus
+	Bus_Controller_Factory -- Sert a instancier chaque controler de bus
+		() -> controller	
+			+ GenerateC -> C_file
+				/*declarations*/
+				...
+				busnb_pre_init(){...}
+				busnb_init(){...}
+				busnb_post_init(){...}
+				busnb_IN(){...}
+				busnb_OUT(){...}
+			+ Save/Load XML
+			+ Save/Load model
+	[Bus_View_Factory -- ]
+	MasterCapable -- Bool, true si peut etre le maitre de synchro
--- a/plugins/__init__.py	Mon Aug 20 14:28:08 2007 +0200
+++ b/plugins/__init__.py	Tue Aug 21 17:21:26 2007 +0200
@@ -1,8 +1,11 @@
 from os import listdir, path
+from xmlclass import DeclareXSDClass
+from __templates import *
 
-base_path = path.split(__file__)[0]
+_base_path = path.split(__file__)[0]
 
-__all__ = [name for name in listdir(base_path) if path.isdir(path.join(base_path, name)) and name != "CVS" or name.endswith(".py") and not name.startswith("__")]
+__all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name != "CVS" or name.endswith(".py") and not name.startswith("__")]
 
 for name in __all__:
     __import__(name, globals(), locals(), [])
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/__templates.py	Tue Aug 21 17:21:26 2007 +0200
@@ -0,0 +1,72 @@
+" Here are base type definitions for plugins "
+
+class PluggableTemplate:
+
+    XSD = None
+    
+    def __init__(self, buspath):
+        pass
+
+    def TestModified(self):
+        return False
+        
+    def ReqSave(self):
+        return False
+
+    def Generate_C(self, dirpath, locations):
+        return [] # [filenames, ...]
+
+    def BlockTypesFactory(self):
+        return []
+
+    def STLibraryFactory(self):
+        return ""
+
+    ViewClass = None
+    View = None
+    def ViewFactory(self):
+        if self.ViewClass:
+            if not self.View:
+                def _onclose():
+                    self.View = None
+                self.View = self.ViewClass()
+                self.View.OnPluggClose = _onclose
+            return self.View
+        return None
+
+
+def _do_BaseParamsClasses():
+    Classes = {}
+    Types = {}
+    GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
+        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+          <xsd:element name="BaseParams">
+            <xsd:complexType>
+              <xsd:attribute name="Enabled" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    CreateClasses(Classes, Types)
+    
+    PluginsBaseParamsClass = Classes["BaseParams"]
+
+    Classes = {}
+    Types = {}
+    GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
+        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+          <xsd:element name="BaseParams">
+            <xsd:complexType>
+              <xsd:attribute name="BusId" type="xsd:integer" use="required" />
+              <xsd:attribute name="Name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+    CreateClasses(Classes, Types)
+    
+    BusBaseParamsClass = Classes["BaseParams"]
+    return PluginsBaseParamsClass, BusBaseParamsClass
+    
+PluginsBaseParamsClass, BusBaseParamsClass = _do_BaseParamsClasses()
+
--- a/plugins/canfestival/__init__.py	Mon Aug 20 14:28:08 2007 +0200
+++ b/plugins/canfestival/__init__.py	Tue Aug 21 17:21:26 2007 +0200
@@ -1,2 +1,1 @@
-from networkedit import networkedit as view
 from canfestival import *
--- a/plugins/canfestival/canfestival.py	Mon Aug 20 14:28:08 2007 +0200
+++ b/plugins/canfestival/canfestival.py	Tue Aug 21 17:21:26 2007 +0200
@@ -1,16 +1,65 @@
+import os
 from nodelist import NodeList
 from nodemanager import NodeManager
 import config_utils, gen_cfile
+from networkedit import networkedit
 
-class _Beremiz_CanFestival_Controller(NodeList):
-    def __init__(self, buspath, bus_id):
-        self.bus_id = bus_id
+class _NetworkEditPlugg(networkedit):
+    def OnCloseFrame(self, event):
+        self.OnPluggClose()
+        event.Skip()
+
+class BusController(NodeList):
+    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
+    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+      <xsd:element name="CanFestivalNode">
+        <xsd:complexType>
+          <xsd:attribute name="CAN_Device" type="xsd:string" use="required" />
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:schema>
+    """
+
+    ViewClass = _NetworkEditPlugg
+    
+    def __init__(self, buspath):
         manager = NodeManager()
         NodeList.__init__(self, manager)
         self.LoadProject(buspath)
 
-    def SaveBus(self):
+    def TestModified(self):
+        return self.HasChanged()
+        
+    def ReqSave(self):
         self.SaveProject()
+        return True
+
+    def Generate_C(self, dirpath, locations):
+        """
+        return C code for network dictionnary
+        """
+        filepath = os.path.join(dirpath, "master.c")
+        master = config_utils.GenerateConciseDCF(locations, self)
+        res = gen_cfile.GenerateFile(filepath, master)
+        if not res:
+             s = str(self.BaseParams.BusId)+"_IN(){}\n"
+             s += "CanOpen(str(\""+self.CanFestivalNode.CAN_Device)+"\")"
+             f = file(filepath, 'a')
+             f.write(s)
+        else:
+             pass # error
+        return {"headers":["master.h"],"sources":["master.c"]}
+    
+class PluginController:
+    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
+    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+      <xsd:element name="CanFestivalInstance">
+        <xsd:complexType>
+          <xsd:attribute name="CAN_Driver" type="xsd:string" use="required" />
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:schema>
+    """
 
     def Generate_C(self, filepath, locations):
         """
@@ -19,14 +68,10 @@
         master = config_utils.GenerateConciseDCF(locations, self)
         res = gen_cfile.GenerateFile(filepath, master)
         if not res:
-             s = str(self.bus_id)+"_IN(){}\n"
+             s = str(self.BaseParams.BusId)+"_IN(){}\n"
+             s += "CanOpen(str(\""+self.CanFestivalNode.CAN_Device)+"\")"
              f = file(filepath, 'a')
              f.write(s)
         else:
              pass # error
 
-def BlockListFactory(bmz_inst):
-    return []
-
-def ControllerFactory():
-  return _Beremiz_CanFestival_Controller()
\ No newline at end of file
--- a/plugins/svgui/svgui.py	Mon Aug 20 14:28:08 2007 +0200
+++ b/plugins/svgui/svgui.py	Tue Aug 21 17:21:26 2007 +0200
@@ -1,60 +1,97 @@
+import os
+from DEFControler import DEFControler
+from defeditor import EditorFrame
 
+class _EditorFramePlugg(EditorFrame):
+    def OnClose(self, event):
+        self.OnPluggClose()
+        event.Skip()
+
+class BusController(DEFControler):
+
+    ViewClass = _EditorFramePlugg
+    
+    def __init__(self, buspath):
+        filepath = os.path.join(buspath, "gui.def")
+        if os.path.isfile(filepath):
+            self.OpenXMLFile(filepath)
+        else
+            self.CreateRootElement()
+            self.SetFilePath(filepath)
+
+    def ReqSave(self):
+        self.SaveXMLFile()
+        return True
+
+    def Generate_C(self, dirpath, locations):
+        self.GenerateProgram(filepath)
+        return {"headers":["program.h"],"sources":["program.cpp"]}
+    
 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
     "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L",
     "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"}
 
-def GetBlockGenerationFunction(beremiz):
-    def generate_svgui_block(generator, block, body, link):
-        controller = generator.GetController()
-        name = block.getInstanceName()
-        type = block.getTypeName()
-        block_infos = GetBlockType(type)
-        bus_id, name = [word for word in name.split("_") if word != ""]
-        block_id = beremiz.GetSVGUIElementId(bus_id, name)
-        if block_id == None:
-            raise ValueError, "No corresponding block found"
-        if not generator.ComputedBlocks.get(name, False):
-            for num, variable in enumerate(block.inputVariables.getVariable()):
-                connections = variable.connectionPointIn.getConnections()
-                if connections and len(connections) == 1:
-                    parameter = "__I%s%d_%d_%d"%(TYPECONVERSION[block_infos["inputs"][num][1]], bus_id, block_id, num)
-                    value = generator.ComputeFBDExpression(body, connections[0])
-                    generator.Program += ("  %s := %s;\n"%(parameter, generator.ExtractModifier(variable, value)))
-            generator.ComputedBlocks[name] = True
-        if link:
-            connectionPoint = link.getPosition()[-1]
-            for num, variable in enumerate(block.outputVariables.getVariable()):
-                blockPointx, blockPointy = variable.connectionPointOut.getRelPosition()
-                if block.getX() + blockPointx == connectionPoint.getX() and block.getY() + blockPointy == connectionPoint.getY():
-                    return "__Q%s%d_%d_%d"%(TYPECONVERSION[block_infos["outputs"][num][1]], bus_id, block_id, num)
-            raise ValueError, "No output variable found"
-        else:
-            return None
-    return generate_svgui_block
+class PluginController:
+    def BlockTypesFactory(self):
+        def generate_svgui_block(generator, block, body, link):
+            controller = generator.GetController()
+            name = block.getInstanceName()
+            type = block.getTypeName()
+            block_infos = GetBlockType(type)
+            bus_id, name = [word for word in name.split("_") if word != ""]
+            block_id = self.PluginBuses[bus_id].GetElementIdFromName(name)
+            if block_id == None:
+                raise ValueError, "No corresponding block found"
+            if not generator.ComputedBlocks.get(name, False):
+                for num, variable in enumerate(block.inputVariables.getVariable()):
+                    connections = variable.connectionPointIn.getConnections()
+                    if connections and len(connections) == 1:
+                        parameter = "__I%s%d_%d_%d"%(TYPECONVERSION[block_infos["inputs"][num][1]], bus_id, block_id, num)
+                        value = generator.ComputeFBDExpression(body, connections[0])
+                        generator.Program += ("  %s := %s;\n"%(parameter, generator.ExtractModifier(variable, value)))
+                generator.ComputedBlocks[name] = True
+            if link:
+                connectionPoint = link.getPosition()[-1]
+                for num, variable in enumerate(block.outputVariables.getVariable()):
+                    blockPointx, blockPointy = variable.connectionPointOut.getRelPosition()
+                    if block.getX() + blockPointx == connectionPoint.getX() and block.getY() + blockPointy == connectionPoint.getY():
+                        return "__Q%s%d_%d_%d"%(TYPECONVERSION[block_infos["outputs"][num][1]], bus_id, block_id, num)
+                raise ValueError, "No output variable found"
+            else:
+                return None
 
-BlockList = {"name" : "SVGUI function blocks", "list" :
-               [{"name" : "Container", "type" : "functionBlock", "extensible" : False, 
-                 "inputs" : [("X","FLOAT","none"),("SetX","BOOL","none"),("Y","FLOAT","none"),("SetY","BOOL","none"),("Angle","FLOAT","none"),("SetAngle","BOOL","none")], 
-                 "outputs" : [("X","FLOAT","none"),("X Changed","BOOL","none"),("Y","FLOAT","none"),("Y Changed","BOOL","none"),("Angle","FLOAT","none"),("Angle Changed","BOOL","none")],
-                 "comment" : "SVGUI Container"},
-                {"name" : "Button", "type" : "functionBlock", "extensible" : False, 
-                 "inputs" : [("Show","BOOL","none"),("Toggle","BOOL","none")], 
-                 "outputs" : [("Visible","BOOL","none"),("State","BOOL","none")],
-                 "comment" : "SVGUI Button"},
-                {"name" : "TextCtrl", "type" : "functionBlock", "extensible" : False, 
-                 "inputs" : [("Text","STRING","none"),("Set Text","BOOL","none")], 
-                 "outputs" : [("Text","STRING","none"),("Text Changed","BOOL","none")],
-                 "comment" : "SVGUI Text Control"},
-                {"name" : "ScrollBar", "type" : "functionBlock", "extensible" : False, 
-                 "inputs" : [("Position","UINT","none"),("Set Position","BOOL","none")], 
-                 "outputs" : [("Position","UINT","none"),("Position Changed","BOOL","none")],
-                 "comment" : "SVGUI ScrollBar"},
-                {"name" : "NoteBook", "type" : "functionBlock", "extensible" : False, 
-                 "inputs" : [("Selected","UINT","none"),("Set Selected","BOOL","none")], 
-                 "outputs" : [("Selected","UINT","none"),("Selected Changed","BOOL","none")],
-                 "comment" : "SVGUI Notebook"},
-                {"name" : "RotatingCtrl", "type" : "functionBlock", "extensible" : False, 
-                 "inputs" : [("Angle","FLOAT","none"),("Set Angle","BOOL","none")], 
-                 "outputs" : [("Angle","FLOAT","none"),("Angle changed","BOOL","none")],
-                 "comment" : "SVGUI Rotating Control"},
-               ]}
+        return [{"name" : "SVGUI function blocks", "list" :
+           [{"name" : "Container", "type" : "functionBlock", "extensible" : False, 
+             "inputs" : [("X","FLOAT","none"),("SetX","BOOL","none"),("Y","FLOAT","none"),("SetY","BOOL","none"),("Angle","FLOAT","none"),("SetAngle","BOOL","none")], 
+             "outputs" : [("X","FLOAT","none"),("X Changed","BOOL","none"),("Y","FLOAT","none"),("Y Changed","BOOL","none"),("Angle","FLOAT","none"),("Angle Changed","BOOL","none")],
+             "comment" : "SVGUI Container", "generate": generate_svgui_block},
+            {"name" : "Button", "type" : "functionBlock", "extensible" : False, 
+             "inputs" : [("Show","BOOL","none"),("Toggle","BOOL","none")], 
+             "outputs" : [("Visible","BOOL","none"),("State","BOOL","none")],
+             "comment" : "SVGUI Button", "generate": generate_svgui_block},
+            {"name" : "TextCtrl", "type" : "functionBlock", "extensible" : False, 
+             "inputs" : [("Text","STRING","none"),("Set Text","BOOL","none")], 
+             "outputs" : [("Text","STRING","none"),("Text Changed","BOOL","none")],
+             "comment" : "SVGUI Text Control", "generate": generate_svgui_block},
+            {"name" : "ScrollBar", "type" : "functionBlock", "extensible" : False, 
+             "inputs" : [("Position","UINT","none"),("Set Position","BOOL","none")], 
+             "outputs" : [("Position","UINT","none"),("Position Changed","BOOL","none")],
+             "comment" : "SVGUI ScrollBar", "generate": generate_svgui_block},
+            {"name" : "NoteBook", "type" : "functionBlock", "extensible" : False, 
+             "inputs" : [("Selected","UINT","none"),("Set Selected","BOOL","none")], 
+             "outputs" : [("Selected","UINT","none"),("Selected Changed","BOOL","none")],
+             "comment" : "SVGUI Notebook", "generate": generate_svgui_block},
+            {"name" : "RotatingCtrl", "type" : "functionBlock", "extensible" : False, 
+             "inputs" : [("Angle","FLOAT","none"),("Set Angle","BOOL","none")], 
+             "outputs" : [("Angle","FLOAT","none"),("Angle changed","BOOL","none")],
+             "comment" : "SVGUI Rotating Control", "generate": generate_svgui_block}
+           ]}]
+
+
+
+
+
+
+
+
+