c_ext/c_ext.py
changeset 721 ecf4d203c4d4
parent 718 5d4dc150b956
child 725 31dade089db5
equal deleted inserted replaced
720:6be032177e2a 721:ecf4d203c4d4
       
     1 import wx
       
     2 import os
       
     3 from xml.dom import minidom
       
     4 import cPickle
       
     5 
       
     6 from xmlclass import *
       
     7 
       
     8 from ConfigTree import ConfigTreeNode, opjimg
       
     9 from CFileEditor import CFileEditor
       
    10 from PLCControler import PLCControler, UndoBuffer, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
       
    11 
       
    12 CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd"))
       
    13 
       
    14 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
       
    15     "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L",
       
    16     "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"}
       
    17 
       
    18 class _Cfile:
       
    19     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
       
    20     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       
    21       <xsd:element name="CExtension">
       
    22         <xsd:complexType>
       
    23           <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/>
       
    24           <xsd:attribute name="LDFLAGS" type="xsd:string" use="required"/>
       
    25         </xsd:complexType>
       
    26       </xsd:element>
       
    27     </xsd:schema>
       
    28     """
       
    29     EditorType = CFileEditor
       
    30     
       
    31     def __init__(self):
       
    32         filepath = self.CFileName()
       
    33         
       
    34         self.CFile = CFileClasses["CFile"]()
       
    35         if os.path.isfile(filepath):
       
    36             xmlfile = open(filepath, 'r')
       
    37             tree = minidom.parse(xmlfile)
       
    38             xmlfile.close()
       
    39             
       
    40             for child in tree.childNodes:
       
    41                 if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile":
       
    42                     self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
       
    43                     self.CreateCFileBuffer(True)
       
    44         else:
       
    45             self.CreateCFileBuffer(False)
       
    46             self.OnCTNSave()
       
    47 
       
    48     def CFileName(self):
       
    49         return os.path.join(self.CTNPath(), "cfile.xml")
       
    50 
       
    51     def GetBaseTypes(self):
       
    52         return self.GetCTRoot().GetBaseTypes()
       
    53 
       
    54     def GetDataTypes(self, basetypes = False, only_locatables = False):
       
    55         return self.GetCTRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables)
       
    56 
       
    57     def GetSizeOfType(self, type):
       
    58         return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None)
       
    59 
       
    60     def SetVariables(self, variables):
       
    61         self.CFile.variables.setvariable([])
       
    62         for var in variables:
       
    63             variable = CFileClasses["variables_variable"]()
       
    64             variable.setname(var["Name"])
       
    65             variable.settype(var["Type"])
       
    66             variable.setclass(var["Class"])
       
    67             self.CFile.variables.appendvariable(variable)
       
    68     
       
    69     def GetVariables(self):
       
    70         datas = []
       
    71         for var in self.CFile.variables.getvariable():
       
    72             datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()})
       
    73         return datas
       
    74 
       
    75     def GetVariableLocationTree(self):
       
    76         '''See ConfigTreeNode.GetVariableLocationTree() for a description.'''
       
    77 
       
    78         current_location = ".".join(map(str, self.GetCurrentLocation()))
       
    79         
       
    80         vars = []
       
    81         input = memory = output = 0
       
    82         for var in self.CFile.variables.getvariable():
       
    83             var_size = self.GetSizeOfType(var.gettype())
       
    84             var_location = ""
       
    85             if var.getclass() == "input":
       
    86                 var_class = LOCATION_VAR_INPUT
       
    87                 if var_size is not None:
       
    88                     var_location = "%%I%s%s.%d"%(var_size, current_location, input)
       
    89                 input += 1
       
    90             elif var.getclass() == "memory":
       
    91                 var_class = LOCATION_VAR_INPUT
       
    92                 if var_size is not None:
       
    93                     var_location = "%%M%s%s.%d"%(var_size, current_location, memory)
       
    94                 memory += 1
       
    95             else:
       
    96                 var_class = LOCATION_VAR_OUTPUT
       
    97                 if var_size is not None:
       
    98                     var_location = "%%Q%s%s.%d"%(var_size, current_location, output)
       
    99                 output += 1
       
   100             vars.append({"name": var.getname(),
       
   101                          "type": var_class,
       
   102                          "size": var_size,
       
   103                          "IEC_type": var.gettype(),
       
   104                          "var_name": var.getname(),
       
   105                          "location": var_location,
       
   106                          "description": "",
       
   107                          "children": []})
       
   108                 
       
   109         return  {"name": self.BaseParams.getName(),
       
   110                 "type": LOCATION_CONFNODE,
       
   111                 "location": self.GetFullIEC_Channel(),
       
   112                 "children": vars}
       
   113 
       
   114     def SetPartText(self, name, text):
       
   115         if name == "Includes":
       
   116             self.CFile.includes.settext(text)
       
   117         elif name == "Globals":
       
   118             self.CFile.globals.settext(text)
       
   119         elif name == "Init":
       
   120             self.CFile.initFunction.settext(text)
       
   121         elif name == "CleanUp":
       
   122             self.CFile.cleanUpFunction.settext(text)
       
   123         elif name == "Retrieve":
       
   124             self.CFile.retrieveFunction.settext(text)
       
   125         elif name == "Publish":
       
   126             self.CFile.publishFunction.settext(text)
       
   127         
       
   128     def GetPartText(self, name):
       
   129         if name == "Includes":
       
   130             return self.CFile.includes.gettext()
       
   131         elif name == "Globals":
       
   132             return self.CFile.globals.gettext()
       
   133         elif name == "Init":
       
   134             return self.CFile.initFunction.gettext()
       
   135         elif name == "CleanUp":
       
   136             return self.CFile.cleanUpFunction.gettext()
       
   137         elif name == "Retrieve":
       
   138             return self.CFile.retrieveFunction.gettext()
       
   139         elif name == "Publish":
       
   140             return self.CFile.publishFunction.gettext()
       
   141         return ""
       
   142                 
       
   143     ConfNodeMethods = [
       
   144         {"bitmap" : os.path.join("images", "EditCfile"),
       
   145          "name" : _("Edit C File"), 
       
   146          "tooltip" : _("Edit C File"),
       
   147          "method" : "_OpenView"},
       
   148     ]
       
   149 
       
   150     def CTNTestModified(self):
       
   151         return self.ChangesToSave or not self.CFileIsSaved()    
       
   152 
       
   153     def OnCTNSave(self):
       
   154         filepath = self.CFileName()
       
   155         
       
   156         text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
       
   157         extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
       
   158                   "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
       
   159                   "xsi:schemaLocation" : "cext_xsd.xsd"}
       
   160         text += self.CFile.generateXMLText("CFile", 0, extras)
       
   161 
       
   162         xmlfile = open(filepath,"w")
       
   163         xmlfile.write(text.encode("utf-8"))
       
   164         xmlfile.close()
       
   165         
       
   166         self.MarkCFileAsSaved()
       
   167         return True
       
   168 
       
   169     def CTNGenerate_C(self, buildpath, locations):
       
   170         """
       
   171         Generate C code
       
   172         @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
       
   173         @param locations: List of complete variables locations \
       
   174             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
       
   175             "NAME" : name of the variable (generally "__IW0_1_2" style)
       
   176             "DIR" : direction "Q","I" or "M"
       
   177             "SIZE" : size "X", "B", "W", "D", "L"
       
   178             "LOC" : tuple of interger for IEC location (0,1,2,...)
       
   179             }, ...]
       
   180         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
       
   181         """
       
   182         current_location = self.GetCurrentLocation()
       
   183         # define a unique name for the generated C file
       
   184         location_str = "_".join(map(str, current_location))
       
   185         
       
   186         text = "/* Code generated by Beremiz c_ext confnode */\n\n"
       
   187         
       
   188         # Adding includes
       
   189         text += "/* User includes */\n"
       
   190         text += self.CFile.includes.gettext()
       
   191         text += "\n"
       
   192         
       
   193         text += """/* Beremiz c_ext confnode includes */
       
   194 #ifdef _WINDOWS_H
       
   195   #include "iec_types.h"
       
   196 #else
       
   197   #include "iec_std_lib.h"
       
   198 #endif
       
   199 
       
   200 """
       
   201 
       
   202         # Adding variables
       
   203         vars = []
       
   204         inputs = memories = outputs = 0
       
   205         for variable in self.CFile.variables.variable:
       
   206             var = {"Name" : variable.getname(), "Type" : variable.gettype()}
       
   207             if variable.getclass() == "input":
       
   208                 var["location"] = "__I%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, inputs)
       
   209                 inputs += 1
       
   210             elif variable.getclass() == "memory":
       
   211                 var["location"] = "__M%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, memories)
       
   212                 memories += 1
       
   213             else:
       
   214                 var["location"] = "__Q%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, outputs)
       
   215                 outputs += 1
       
   216             vars.append(var)
       
   217         text += "/* Beremiz c_ext confnode user variables definition */\n"
       
   218         base_types = self.GetCTRoot().GetBaseTypes()
       
   219         for var in vars:
       
   220             if var["Type"] in base_types:
       
   221                 prefix = "IEC_"
       
   222             else:
       
   223                 prefix = ""
       
   224             text += "%s%s beremiz%s;\n"%(prefix, var["Type"], var["location"])
       
   225             text += "%s%s *%s = &beremiz%s;\n"%(prefix, var["Type"], var["location"], var["location"])
       
   226         text += "/* User variables reference */\n"
       
   227         for var in vars:
       
   228             text += "#define %s beremiz%s\n"%(var["Name"], var["location"])
       
   229         text += "\n"
       
   230         
       
   231         # Adding user global variables and routines
       
   232         text += "/* User internal user variables and routines */\n"
       
   233         text += self.CFile.globals.gettext()
       
   234         
       
   235         # Adding Beremiz confnode functions
       
   236         text += "/* Beremiz confnode functions */\n"
       
   237         text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
       
   238         text += self.CFile.initFunction.gettext()
       
   239         text += "  return 0;\n"
       
   240         text += "\n}\n\n"
       
   241         
       
   242         text += "void __cleanup_%s(void)\n{\n"%location_str
       
   243         text += self.CFile.cleanUpFunction.gettext()
       
   244         text += "\n}\n\n"
       
   245         
       
   246         text += "void __retrieve_%s(void)\n{\n"%location_str
       
   247         text += self.CFile.retrieveFunction.gettext()
       
   248         text += "\n}\n\n"
       
   249         
       
   250         text += "void __publish_%s(void)\n{\n"%location_str
       
   251         text += self.CFile.publishFunction.gettext()
       
   252         text += "\n}\n\n"
       
   253         
       
   254         Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
       
   255         cfile = open(Gen_Cfile_path,'w')
       
   256         cfile.write(text)
       
   257         cfile.close()
       
   258         
       
   259         matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath())
       
   260         
       
   261         return [(Gen_Cfile_path, str(self.CExtension.getCFLAGS() + matiec_flags))],str(self.CExtension.getLDFLAGS()),True
       
   262 
       
   263 
       
   264 #-------------------------------------------------------------------------------
       
   265 #                      Current Buffering Management Functions
       
   266 #-------------------------------------------------------------------------------
       
   267 
       
   268     """
       
   269     Return a copy of the cfile model
       
   270     """
       
   271     def Copy(self, model):
       
   272         return cPickle.loads(cPickle.dumps(model))
       
   273 
       
   274     def CreateCFileBuffer(self, saved):
       
   275         self.Buffering = False
       
   276         self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved)
       
   277 
       
   278     def BufferCFile(self):
       
   279         self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
       
   280     
       
   281     def StartBuffering(self):
       
   282         self.Buffering = True
       
   283         
       
   284     def EndBuffering(self):
       
   285         if self.Buffering:
       
   286             self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
       
   287             self.Buffering = False
       
   288     
       
   289     def MarkCFileAsSaved(self):
       
   290         self.EndBuffering()
       
   291         self.CFileBuffer.CurrentSaved()
       
   292     
       
   293     def CFileIsSaved(self):
       
   294         return self.CFileBuffer.IsCurrentSaved() and not self.Buffering
       
   295         
       
   296     def LoadPrevious(self):
       
   297         self.EndBuffering()
       
   298         self.CFile = cPickle.loads(self.CFileBuffer.Previous())
       
   299     
       
   300     def LoadNext(self):
       
   301         self.CFile = cPickle.loads(self.CFileBuffer.Next())
       
   302     
       
   303     def GetBufferState(self):
       
   304         first = self.CFileBuffer.IsFirst() and not self.Buffering
       
   305         last = self.CFileBuffer.IsLast()
       
   306         return not first, not last
       
   307 
       
   308 class RootClass:
       
   309 
       
   310     CTNChildrenTypes = [("C_File",_Cfile, "C file")]
       
   311     
       
   312     def CTNGenerate_C(self, buildpath, locations):
       
   313         return [],"",False
       
   314 
       
   315